home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-serious-
/
programming
/
other
/
jikes-1.11
/
src
/
decl.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-23
|
190KB
|
4,608 lines
// $Id: decl.cpp,v 1.40 2000/01/06 08:24:30 lord Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://www.ibm.com/research/jikes.
// Copyright (C) 1996, 1998, International Business Machines Corporation
// and others. All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
#include "config.h"
#include <sys/stat.h>
#include "semantic.h"
#include "control.h"
#include "depend.h"
#include "table.h"
#include "tuple.h"
//
// If this compilation unit contains a package declaration, make sure the package
// is associated with a directory and that the name of the package is not also
// associated with a type.
//
inline void Semantic::CheckPackage()
{
if (compilation_unit -> package_declaration_opt)
{
//
// Make sure that the package actually exists.
//
if (this_package -> directory.Length() == 0 && control.option.directory == NULL)
{
ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
compilation_unit -> package_declaration_opt -> name -> LeftToken(),
compilation_unit -> package_declaration_opt -> name -> RightToken(),
this_package -> PackageName());
}
else
{
//
// Make sure that the package or any of its parents does not match the name of a type.
//
for (PackageSymbol *subpackage = this_package, *package = subpackage -> owner;
package;
subpackage = package, package = package -> owner)
{
FileSymbol *file_symbol = Control::GetFile(control, package, subpackage -> Identity());
if (file_symbol)
{
char *file_name = file_symbol -> FileName();
int length = file_symbol -> FileNameLength();
wchar_t *error_name = new wchar_t[length + 1];
for (int i = 0; i < length; i++)
error_name[i] = file_name[i];
error_name[length] = U_NULL;
ReportSemError(SemanticError::PACKAGE_TYPE_CONFLICT,
compilation_unit -> package_declaration_opt -> name -> LeftToken(),
compilation_unit -> package_declaration_opt -> name -> RightToken(),
package -> PackageName(),
subpackage -> Name(),
error_name);
delete [] error_name;
}
}
}
}
return;
}
//
// Pass 1: Introduce the main package, the current package and all types specified into their proper scope
//
void Semantic::ProcessTypeNames()
{
import_on_demand_packages.Next() = control.system_package;
compilation_unit = source_file_symbol -> compilation_unit;
//
// If we are supposed to be verbose, report empty declarations...
//
if (control.option.pedantic)
{
if (compilation_unit -> EmptyCompilationUnitCast())
{
ReportSemError(SemanticError::NO_TYPES,
compilation_unit -> LeftToken(),
compilation_unit -> RightToken());
}
for (int i = 0; i < compilation_unit -> NumTypeDeclarations(); i++)
{
Ast *type_declaration = compilation_unit -> TypeDeclaration(i);
if (type_declaration -> EmptyDeclarationCast())
{
ReportSemError(SemanticError::EMPTY_DECLARATION,
type_declaration -> LeftToken(),
type_declaration -> RightToken());
}
}
}
//
// If we have a bad compilation unit insert its types as "bad types"
//
if (compilation_unit -> BadCompilationUnitCast())
{
for (int i = 0; i < lex_stream -> NumTypes(); i++)
{
LexStream::TokenIndex identifier_token = lex_stream -> Next(lex_stream -> Type(i));
if (lex_stream -> Kind(identifier_token) == TK_Identifier)
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
TypeSymbol *type = this_package -> FindTypeSymbol(name_symbol);
assert(type);
type -> MarkBad();
type -> MarkSourceNoLongerPending();
type -> supertypes_closure = new SymbolSet;
type -> subtypes = new SymbolSet;
type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL);
if (type != control.Object())
type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
if (! type -> FindConstructorSymbol())
AddDefaultConstructor(type);
source_file_symbol -> types.Next() = type;
}
}
return;
}
//
// Use this tuple to compute the list of valid types encountered in this
// compilation unit.
//
Tuple<TypeSymbol *> type_list;
//
// Process each type in this compilation unit, in turn
//
for (int k = 0; k < compilation_unit -> NumTypeDeclarations(); k++)
{
LexStream::TokenIndex identifier_token;
TypeSymbol *type = NULL;
Ast *type_declaration = compilation_unit -> TypeDeclaration(k);
switch(type_declaration -> kind)
{
case Ast::CLASS:
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) type_declaration;
identifier_token = class_declaration -> identifier_token;
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
type = this_package -> FindTypeSymbol(name_symbol);
if (type)
{
if (! type -> SourcePending())
{
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
identifier_token,
identifier_token,
name_symbol -> Name(),
type -> FileLoc());
type = NULL;
}
else
{
if (type -> ContainingPackage() == control.unnamed_package)
{
TypeSymbol *old_type = (TypeSymbol *) control.unnamed_package_types.Image(name_symbol);
if (old_type != type)
{
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
identifier_token,
identifier_token,
name_symbol -> Name(),
old_type -> FileLoc());
}
}
type_list.Next() = type; // Save valid type for later processing. See below
type -> MarkSourceNoLongerPending();
type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL);
type -> declaration = class_declaration;
type -> SetFlags(ProcessClassModifiers(class_declaration));
//
// Add 3 extra elements for padding. May need a default constructor and other support elements.
//
type -> SetSymbolTable(class_declaration -> class_body -> NumClassBodyDeclarations() + 3);
type -> SetLocation();
if (lex_stream -> IsDeprecated(lex_stream -> Previous(class_declaration -> LeftToken())))
type -> MarkDeprecated();
source_file_symbol -> types.Next() = type;
class_declaration -> semantic_environment = type -> semantic_environment; // save for processing bodies later.
CheckClassMembers(type, class_declaration -> class_body);
}
}
break;
}
case Ast::INTERFACE:
{
AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type_declaration;
identifier_token = interface_declaration -> identifier_token;
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
type = this_package -> FindTypeSymbol(name_symbol);
if (type)
{
if (! type -> SourcePending())
{
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
identifier_token,
identifier_token,
name_symbol -> Name(),
type -> FileLoc());
type = NULL;
}
else
{
if (type -> ContainingPackage() == control.unnamed_package)
{
TypeSymbol *old_type = (TypeSymbol *) control.unnamed_package_types.Image(name_symbol);
if (old_type != type)
{
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
identifier_token,
identifier_token,
name_symbol -> Name(),
old_type -> FileLoc());
}
}
type_list.Next() = type; // Save valid type for later processing. See below
type -> MarkSourceNoLongerPending();
type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL);
type -> declaration = interface_declaration;
type -> file_symbol = source_file_symbol;
type -> SetFlags(ProcessInterfaceModifiers(interface_declaration));
type -> SetSymbolTable(interface_declaration -> NumInterfaceMemberDeclarations());
type -> SetLocation();
if (lex_stream -> IsDeprecated(lex_stream -> Previous(interface_declaration -> LeftToken())))
type -> MarkDeprecated();
source_file_symbol -> types.Next() = type;
interface_declaration -> semantic_environment = type -> semantic_environment;
CheckInterfaceMembers(type, interface_declaration);
}
}
break;
}
case Ast::EMPTY_DECLARATION:
break;
default:
assert(false);
break;
}
//
// If we successfully processed this type, check that
// . its name does not conflict with a subpackage
// . if it is contained in a file with a diffent name
// than its own name that there does not also exist a
// (java or class) file with its name.
//
if (type)
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
for (int i = 0; i < this_package -> directory.Length(); i++)
{
if (this_package -> directory[i] -> FindDirectorySymbol(name_symbol))
{
char *file_name = type -> file_symbol -> FileName();
int length = type -> file_symbol -> FileNameLength();
wchar_t *error_name = new wchar_t[length + 1];
for (int j = 0; j < length; j++)
error_name[j] = file_name[j];
error_name[length] = U_NULL;
ReportSemError(SemanticError::PACKAGE_TYPE_CONFLICT,
identifier_token,
identifier_token,
this_package -> PackageName(),
name_symbol -> Name(),
error_name);
delete [] error_name;
}
}
if (type -> Identity() != source_file_symbol -> Identity())
{
PackageSymbol *package = this_package;
FileSymbol *file_symbol = Control::GetJavaFile(package, type -> Identity());
if (file_symbol)
{
ReportSemError(SemanticError::TYPE_IN_MULTIPLE_FILES,
identifier_token,
identifier_token,
this_package -> PackageName(),
source_file_symbol -> Name(),
package -> PackageName(),
type -> Name());
}
}
}
}
CheckPackage();
ProcessImports();
//
// Process outer type of superclasses and interfaces and make sure that compilation unit
// contains exactly one public type.
//
TypeSymbol *public_type = NULL;
for (int i = 0; i < type_list.Length(); i++)
{
TypeSymbol *type = type_list[i];
AstClassDeclaration *class_declaration = type -> declaration -> ClassDeclarationCast();
AstInterfaceDeclaration *interface_declaration = type -> declaration -> InterfaceDeclarationCast();
if (class_declaration)
ProcessSuperTypeDependences(class_declaration);
else ProcessSuperTypeDependences(interface_declaration);
if (type && type -> ACC_PUBLIC())
{
if (! public_type)
{
public_type = type;
if (source_file_symbol -> Identity() != public_type -> Identity())
{
if (class_declaration)
{
ReportSemError(SemanticError::MISMATCHED_TYPE_AND_FILE_NAMES,
class_declaration -> identifier_token,
class_declaration -> identifier_token,
public_type -> Name());
}
else
{
ReportSemError(SemanticError::MISMATCHED_TYPE_AND_FILE_NAMES,
interface_declaration -> identifier_token,
interface_declaration -> identifier_token,
public_type -> Name());
}
}
}
else
{
if (class_declaration)
{
ReportSemError(SemanticError::MULTIPLE_PUBLIC_TYPES,
class_declaration -> identifier_token,
class_declaration -> identifier_token,
type -> Name(),
public_type -> Name());
}
else
{
ReportSemError(SemanticError::MULTIPLE_PUBLIC_TYPES,
interface_declaration -> identifier_token,
interface_declaration -> identifier_token,
type -> Name(),
public_type -> Name());
}
}
}
}
return;
}
void Semantic::CheckClassMembers(TypeSymbol *containing_type, AstClassBody *class_body)
{
for (int i = 0; i < class_body -> NumNestedClasses(); i++)
{
AstClassDeclaration *class_declaration = class_body -> NestedClass(i);
ProcessNestedClassName(containing_type, class_declaration);
}
for (int j = 0; j < class_body -> NumNestedInterfaces(); j++)
{
AstInterfaceDeclaration *interface_declaration = class_body -> NestedInterface(j);
ProcessNestedInterfaceName(containing_type, interface_declaration);
}
for (int l = 0; l < class_body -> NumEmptyDeclarations(); l++)
{
if (control.option.pedantic)
{
ReportSemError(SemanticError::EMPTY_DECLARATION,
class_body -> EmptyDeclaration(l) -> LeftToken(),
class_body -> EmptyDeclaration(l) -> RightToken());
}
}
return;
}
inline TypeSymbol *Semantic::FindTypeInShadow(TypeShadowSymbol *type_shadow_symbol, LexStream::TokenIndex identifier_token)
{
//
// Recall that even an inaccessible member x of a super class (or interface) S,
// in addition to not been inherited by a subclass, hides all other occurrences of x that may
// appear in a super class (or super interface) of S (see 8.3).
//
TypeSymbol *type_symbol = type_shadow_symbol -> type_symbol;
for (int i = 0; i < type_shadow_symbol -> NumConflicts(); i++)
{
ReportSemError(SemanticError::AMBIGUOUS_TYPE,
identifier_token,
identifier_token,
type_symbol -> Name(),
type_symbol -> owner -> TypeCast() -> ContainingPackage() -> PackageName(),
type_symbol -> owner -> TypeCast() -> ExternalName(),
type_shadow_symbol -> Conflict(i) -> owner -> TypeCast() -> ContainingPackage() -> PackageName(),
type_shadow_symbol -> Conflict(i) -> owner -> TypeCast() -> ExternalName());
}
return type_symbol;
}
//
// Look for a type within an environment stack, without regard to inheritance !!!
//
TypeSymbol *Semantic::FindTypeInEnvironment(SemanticEnvironment *env_stack, NameSymbol *name_symbol)
{
for (SemanticEnvironment *env = env_stack; env; env = env -> previous)
{
TypeSymbol *type = env -> symbol_table.FindTypeSymbol(name_symbol);
if (type)
return type;
type = env -> Type() -> FindTypeSymbol(name_symbol);
if (type)
return type;
if (name_symbol == env -> Type() -> Identity())
return env -> Type();
}
return (TypeSymbol *) NULL;
}
void Semantic::CheckNestedTypeDuplication(SemanticEnvironment *env, LexStream::TokenIndex identifier_token)
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
//
// First check to see if we have a duplication at the same level...
//
TypeSymbol *old_type = (env -> symbol_table.Size() > 0 ? env -> symbol_table.Top() -> FindTypeSymbol(name_symbol)
: env -> Type() -> FindTypeSymbol(name_symbol));
if (old_type)
{
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
identifier_token,
identifier_token,
name_symbol -> Name(),
old_type -> FileLoc());
}
else
{
//
// ... Then check the enclosing environments...
//
for (; env; env = env -> previous)
{
if (env -> Type() -> Identity() == name_symbol)
{
ReportSemError(SemanticError::DUPLICATE_INNER_TYPE_NAME,
identifier_token,
identifier_token,
name_symbol -> Name(),
env -> Type() -> FileLoc());
break;
}
}
}
return;
}
TypeSymbol *Semantic::ProcessNestedClassName(TypeSymbol *containing_type, AstClassDeclaration *class_declaration)
{
CheckNestedTypeDuplication(containing_type -> semantic_environment, class_declaration -> identifier_token);
NameSymbol *name_symbol = lex_stream -> NameSymbol(class_declaration -> identifier_token);
TypeSymbol *outermost_type = containing_type -> outermost_type;
int length = containing_type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $
wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(external_name, containing_type -> ExternalName());
wcscat(external_name, StringConstant::US__DS);
wcscat(external_name, name_symbol -> Name());
TypeSymbol *inner_type = containing_type -> InsertNestedTypeSymbol(name_symbol);
inner_type -> outermost_type = outermost_type;
inner_type -> supertypes_closure = new SymbolSet;
inner_type -> subtypes = new SymbolSet;
inner_type -> SetExternalIdentity(control.FindOrInsertName(external_name, length));
inner_type -> semantic_environment = new SemanticEnvironment((Semantic *) this,
inner_type,
containing_type -> semantic_environment);
inner_type -> declaration = class_declaration;
inner_type -> file_symbol = source_file_symbol;
inner_type -> SetFlags(containing_type -> ACC_INTERFACE()
? ProcessStaticNestedClassModifiers(class_declaration)
: ProcessNestedClassModifiers(class_declaration));
inner_type -> SetOwner(containing_type);
//
// Add 3 extra elements for padding. May need a default constructor and other support elements.
//
inner_type -> SetSymbolTable(class_declaration -> class_body -> NumClassBodyDeclarations() + 3);
inner_type -> SetLocation();
inner_type -> SetSignature(control);
if (lex_stream -> IsDeprecated(lex_stream -> Previous(class_declaration -> LeftToken())))
inner_type -> MarkDeprecated();
//
// If not a top-level type, then add pointer to enclosing type.
//
if (! inner_type -> ACC_STATIC())
inner_type -> InsertThis(0);
if (inner_type -> IsLocal())
{
if (! outermost_type -> local)
outermost_type -> local = new SymbolSet;
outermost_type -> local -> AddElement(inner_type);
}
else
{
if (! outermost_type -> non_local)
outermost_type -> non_local = new SymbolSet;
outermost_type -> non_local -> AddElement(inner_type);
}
class_declaration -> semantic_environment = inner_type -> semantic_environment; // save for processing bodies later.
CheckClassMembers(inner_type, class_declaration -> class_body);
delete [] external_name;
return inner_type;
}
void Semantic::CheckInterfaceMembers(TypeSymbol *containing_type, AstInterfaceDeclaration *interface_declaration)
{
for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++)
{
AstClassDeclaration *class_declaration = interface_declaration -> NestedClass(i);
ProcessNestedClassName(containing_type, class_declaration);
}
for (int j = 0; j < interface_declaration -> NumNestedInterfaces(); j++)
{
AstInterfaceDeclaration *inner_interface_declaration = interface_declaration -> NestedInterface(j);
ProcessNestedInterfaceName(containing_type, inner_interface_declaration);
}
for (int l = 0; l < interface_declaration -> NumEmptyDeclarations(); l++)
{
if (control.option.pedantic)
{
ReportSemError(SemanticError::EMPTY_DECLARATION,
interface_declaration -> EmptyDeclaration(l) -> LeftToken(),
interface_declaration -> EmptyDeclaration(l) -> RightToken());
}
}
return;
}
TypeSymbol *Semantic::ProcessNestedInterfaceName(TypeSymbol *containing_type, AstInterfaceDeclaration *interface_declaration)
{
CheckNestedTypeDuplication(containing_type -> semantic_environment, interface_declaration -> identifier_token);
NameSymbol *name_symbol = lex_stream -> NameSymbol(interface_declaration -> identifier_token);
TypeSymbol *outermost_type = containing_type -> outermost_type;
int length = containing_type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $
wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(external_name, containing_type -> ExternalName());
wcscat(external_name, StringConstant::US__DS);
wcscat(external_name, name_symbol -> Name());
TypeSymbol *inner_type = containing_type -> InsertNestedTypeSymbol(name_symbol);
inner_type -> outermost_type = outermost_type;
inner_type -> supertypes_closure = new SymbolSet;
inner_type -> subtypes = new SymbolSet;
inner_type -> SetExternalIdentity(control.FindOrInsertName(external_name, length));
inner_type -> semantic_environment = new SemanticEnvironment((Semantic *) this,
inner_type,
containing_type -> semantic_environment);
inner_type -> declaration = interface_declaration;
inner_type -> file_symbol = source_file_symbol;
inner_type -> SetFlags(ProcessNestedInterfaceModifiers(interface_declaration));
inner_type -> SetOwner(containing_type);
inner_type -> SetSymbolTable(interface_declaration -> NumInterfaceMemberDeclarations());
inner_type -> SetLocation();
inner_type -> SetSignature(control);
if (lex_stream -> IsDeprecated(lex_stream -> Previous(interface_declaration -> LeftToken())))
inner_type -> MarkDeprecated();
if (inner_type -> IsLocal())
{
if (! outermost_type -> local)
outermost_type -> local = new SymbolSet;
outermost_type -> local -> AddElement(inner_type);
}
else
{
if (! outermost_type -> non_local)
outermost_type -> non_local = new SymbolSet;
outermost_type -> non_local -> AddElement(inner_type);
}
interface_declaration -> semantic_environment = inner_type -> semantic_environment; // save for processing bodies later.
CheckInterfaceMembers(inner_type, interface_declaration);
delete [] external_name;
return inner_type;
}
//
// Pass 1.2: Process all import statements
//
void Semantic::ProcessImports()
{
for (int i = 0; i < compilation_unit -> NumImportDeclarations(); i++)
{
AstImportDeclaration *import_declaration = compilation_unit -> ImportDeclaration(i);
if (import_declaration -> star_token_opt)
ProcessTypeImportOnDemandDeclaration(import_declaration);
else ProcessSingleTypeImportDeclaration(import_declaration);
}
return;
}
//
// Pass 1.3: Process outer types in "extends" and "implements" clauses associated with the types.
//
void Semantic::ProcessSuperTypeDependences(AstClassDeclaration *class_declaration)
{
TypeSymbol *type = class_declaration -> semantic_environment -> Type();
if (class_declaration -> super_opt)
{
TypeSymbol *super_type = FindFirstType(class_declaration -> super_opt) -> symbol -> TypeCast();
if (super_type)
super_type -> subtypes -> AddElement(type -> outermost_type);
}
for (int k = 0; k < class_declaration -> NumInterfaces(); k++)
{
TypeSymbol *super_type = FindFirstType(class_declaration -> Interface(k)) -> symbol -> TypeCast();
if (super_type)
{
assert(super_type -> subtypes);
super_type -> subtypes -> AddElement(type -> outermost_type);
}
}
SetDefaultSuperType(class_declaration);
AstClassBody *class_body = class_declaration -> class_body;
for (int i = 0; i < class_body -> NumNestedClasses(); i++)
ProcessSuperTypeDependences(class_body -> NestedClass(i));
for (int j = 0; j < class_body -> NumNestedInterfaces(); j++)
ProcessSuperTypeDependences(class_body -> NestedInterface(j));
return;
}
void Semantic::ProcessSuperTypeDependences(AstInterfaceDeclaration *interface_declaration)
{
TypeSymbol *type = interface_declaration -> semantic_environment -> Type();
for (int k = 0; k < interface_declaration -> NumExtendsInterfaces(); k++)
{
TypeSymbol *super_type = FindFirstType(interface_declaration -> ExtendsInterface(k)) -> symbol -> TypeCast();
if (super_type)
super_type -> subtypes -> AddElement(type -> outermost_type);
}
SetDefaultSuperType(interface_declaration);
for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++)
ProcessSuperTypeDependences(interface_declaration -> NestedClass(i));
for (int j = 0; j < interface_declaration -> NumNestedInterfaces(); j++)
ProcessSuperTypeDependences(interface_declaration -> NestedInterface(j));
return;
}
void Semantic::SetDefaultSuperType(AstClassDeclaration *class_declaration)
{
TypeSymbol *type = class_declaration -> semantic_environment -> Type();
//
// If a type has no super type, set it up properly in case
// it is expanded prematurely by one of its dependents.
//
if (! class_declaration -> super_opt && class_declaration -> NumInterfaces() == 0)
{
if (type -> Identity() != control.object_name_symbol ||
type -> ContainingPackage() != control.system_package || type -> IsNested())
type -> super = control.Object();
}
return;
}
void Semantic::SetDefaultSuperType(AstInterfaceDeclaration *interface_declaration)
{
TypeSymbol *type = interface_declaration -> semantic_environment -> Type();
//
// Set it up an interface properly in case it is
// expanded prematurely by one of its dependents.
//
type -> super = control.Object();
for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++)
{
AstClassDeclaration *inner_class_declaration = interface_declaration -> NestedClass(i);
if (inner_class_declaration -> semantic_environment)
SetDefaultSuperType(inner_class_declaration);
}
for (int j = 0; j < interface_declaration -> NumNestedInterfaces(); j++)
{
AstInterfaceDeclaration *inner_interface_declaration = interface_declaration -> NestedInterface(j);
if (inner_interface_declaration -> semantic_environment)
SetDefaultSuperType(inner_interface_declaration);
}
return;
}
//
// Pass 2: Process "extends" and "implements" clauses associated with the types.
//
void Semantic::ProcessTypeHeader(AstClassDeclaration *class_declaration)
{
TypeSymbol *this_type = class_declaration -> semantic_environment -> Type();
assert(! this_type -> HeaderProcessed() || this_type -> Bad());
//
// If the class does not have a super type then ...
//
if (! class_declaration -> super_opt)
{
if (this_type -> Identity() != control.object_name_symbol ||
this_package != control.system_package || this_type -> IsNested())
SetObjectSuperType(this_type, class_declaration -> identifier_token);
}
else
{
TypeSymbol *super_type = MustFindType(class_declaration -> super_opt);
assert(this_type -> subtypes_closure);
assert(! super_type -> SourcePending());
this_type -> super = super_type;
if (this_type -> subtypes_closure -> IsElement(super_type)) // if there is a cycle, break it and issue an error message
{
this_type -> super = control.Object();
this_type -> MarkCircular();
ReportSemError(SemanticError::CIRCULAR_CLASS,
class_declaration -> identifier_token,
class_declaration -> super_opt -> RightToken(),
this_type -> ContainingPackage() -> PackageName(),
this_type -> ExternalName());
}
else if (this_type -> Identity() == control.object_name_symbol &&
this_package == control.system_package && (! this_type -> IsNested()))
{
ReportSemError(SemanticError::OBJECT_WITH_SUPER_TYPE,
class_declaration -> super_opt -> LeftToken(),
class_declaration -> super_opt -> RightToken(),
this_type -> ContainingPackage() -> PackageName(),
this_type -> ExternalName());
this_type -> super = NULL;
}
else if (this_type -> super -> ACC_INTERFACE())
{
ReportSemError(SemanticError::NOT_A_CLASS,
class_declaration -> super_opt -> LeftToken(),
class_declaration -> super_opt -> RightToken(),
this_type -> super -> ContainingPackage() -> PackageName(),
this_type -> super -> ExternalName());
SetObjectSuperType(this_type, class_declaration -> identifier_token);
}
else if (this_type -> super -> ACC_FINAL())
{
ReportSemError(SemanticError::SUPER_IS_FINAL,
class_declaration -> super_opt -> LeftToken(),
class_declaration -> super_opt -> RightToken(),
this_type -> super -> ContainingPackage() -> PackageName(),
this_type -> super -> ExternalName());
}
}
for (int i = 0; i < class_declaration -> NumInterfaces(); i++)
ProcessInterface(this_type, class_declaration -> Interface(i));
this_type -> MarkHeaderProcessed();
return;
}
void Semantic::ProcessTypeHeader(AstInterfaceDeclaration *interface_declaration)
{
TypeSymbol *this_type = interface_declaration -> semantic_environment -> Type();
assert(! this_type -> HeaderProcessed() || this_type -> Bad());
SetObjectSuperType(this_type, interface_declaration -> identifier_token);
for (int k = 0; k < interface_declaration -> NumExtendsInterfaces(); k++)
ProcessInterface(this_type, interface_declaration -> ExtendsInterface(k));
assert(this_type -> subtypes_closure);
for (int i = 0; i < this_type -> NumInterfaces(); i++)
{
if (this_type -> subtypes_closure -> IsElement(this_type -> Interface(i)))
{
this_type -> ResetInterfaces(); // Remove all the interfaces if a loop is detected. The error will be reported later
this_type -> MarkCircular();
ReportSemError(SemanticError::CIRCULAR_INTERFACE,
interface_declaration -> identifier_token,
interface_declaration -> ExtendsInterface(interface_declaration -> NumExtendsInterfaces() - 1) -> RightToken(),
this_type -> ContainingPackage() -> PackageName(),
this_type -> ExternalName());
break;
}
}
this_type -> MarkHeaderProcessed();
return;
}
//
// Marked type and all other types that are nested inside it "circular"
//
void Semantic::MarkCircularNest(TypeSymbol *type)
{
if (type -> Circular())
return;
//
// Mark the type as circular
//
type -> MarkCircular();
type -> super = control.Object();
type -> ResetInterfaces();
//
// Recursively, process any nested type...
//
AstClassDeclaration *class_declaration = type -> declaration -> ClassDeclarationCast();
if (class_declaration)
{
AstClassBody *class_body = class_declaration -> class_body;
for (int i = 0; i < class_body -> NumNestedClasses(); i++)
MarkCircularNest(class_body -> NestedClass(i) -> semantic_environment -> Type());
for (int k = 0; k < class_body -> NumNestedInterfaces(); k++)
MarkCircularNest(class_body -> NestedInterface(k) -> semantic_environment -> Type());
}
else
{
AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type -> declaration;
for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++)
MarkCircularNest(interface_declaration -> NestedClass(i) -> semantic_environment -> Type());
for (int k = 0; k < interface_declaration -> NumNestedInterfaces(); k++)
MarkCircularNest(interface_declaration -> NestedInterface(k) -> semantic_environment -> Type());
}
return;
}
//
// Compute the set of super types associated with this outer-level type
// and check for circularity.
//
void Semantic::ProcessSuperTypesOfOuterType(TypeSymbol *type)
{
assert((! type -> IsNested()) || type -> owner -> MethodCast());
if (type -> super)
{
type -> supertypes_closure -> AddElement(type -> super -> outermost_type);
type -> supertypes_closure -> Union(*type -> super -> outermost_type -> supertypes_closure);
}
for (int k = 0; k < type -> NumInterfaces(); k++)
{
type -> supertypes_closure -> AddElement(type -> Interface(k) -> outermost_type);
type -> supertypes_closure -> Union(*type -> Interface(k) -> outermost_type -> supertypes_closure);
}
SymbolSet &inner_types = *(type -> innertypes_closure);
for (TypeSymbol *inner_type = (TypeSymbol *) inner_types.FirstElement();
inner_type;
inner_type = (TypeSymbol *) inner_types.NextElement())
{
TypeSymbol *super_type = inner_type -> super;
for (int k = 0; super_type;
super_type = (TypeSymbol *) (k < inner_type -> NumInterfaces() ? inner_type -> Interface(k++) : NULL))
{
if (super_type -> outermost_type != type)
{
type -> supertypes_closure -> AddElement(super_type -> outermost_type);
type -> supertypes_closure -> Union(*super_type -> outermost_type -> supertypes_closure);
}
}
}
bool circular = type -> supertypes_closure -> IsElement(type) ||
type -> subtypes_closure -> Intersects(*type -> supertypes_closure);
if (circular)
{
if (type -> Circular()) // If the type is already marked circular, an error message has already been issued
type -> MarkNonCircular(); // Remove the circular mark, so that we can remark the whole "nest" ?
else
{
if (type -> ACC_INTERFACE())
{
AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type -> declaration;
int right_token_index = interface_declaration -> NumExtendsInterfaces() - 1;
ReportSemError(SemanticError::CIRCULAR_INTERFACE,
interface_declaration -> identifier_token,
(interface_declaration -> NumExtendsInterfaces() > 0
? interface_declaration -> ExtendsInterface(right_token_index) -> RightToken()
: interface_declaration -> identifier_token),
type -> ContainingPackage() -> PackageName(),
type -> ExternalName());
}
else
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) type -> declaration;
int right_token_index = class_declaration -> NumInterfaces() - 1;
ReportSemError(SemanticError::CIRCULAR_CLASS,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(right_token_index) -> RightToken()
: (class_declaration -> super_opt
? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
type -> ContainingPackage() -> PackageName(),
type -> ExternalName());
SetObjectSuperType(type, class_declaration -> identifier_token);
assert(type -> Identity() != control.object_name_symbol || type -> ContainingPackage() != control.system_package);
}
}
MarkCircularNest(type);
}
return;
}
//
// The array partially_ordered_types contains a list of inner types. For
// each of these types, compute the set of super types associated with it
// and check for circularity.
//
void Semantic::ProcessSuperTypesOfInnerType(TypeSymbol *type, Tuple<TypeSymbol *> &partially_ordered_types)
{
for (int l = 0; l < partially_ordered_types.Length(); l++)
{
TypeSymbol *inner_type = partially_ordered_types[l];
SymbolSet &nested_types = *(inner_type -> innertypes_closure);
nested_types.AddElement(inner_type); // Compute reflexive transitive closure
for (TypeSymbol *nested_type = (TypeSymbol *) nested_types.FirstElement();
nested_type;
nested_type = (TypeSymbol *) nested_types.NextElement())
{
TypeSymbol *super_type = nested_type -> super;
for (int k = 0; super_type;
super_type = (TypeSymbol *) (k < nested_type -> NumInterfaces() ? nested_type -> Interface(k++) : NULL))
{
for ( ; super_type; super_type = super_type -> owner -> TypeCast())
{
if (type -> innertypes_closure -> IsElement(super_type))
break;
}
if (super_type && super_type != inner_type)
{
inner_type -> supertypes_closure -> AddElement(super_type);
inner_type -> supertypes_closure -> Union(*super_type -> supertypes_closure);
}
}
}
bool circular = inner_type -> supertypes_closure -> IsElement(inner_type) ||
inner_type -> subtypes_closure -> Intersects(*inner_type -> supertypes_closure);
if (circular)
{
MarkCircularNest(inner_type);
if (inner_type -> ACC_INTERFACE())
{
AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration;
ReportSemError(SemanticError::CIRCULAR_INTERFACE,
interface_declaration -> identifier_token,
(interface_declaration -> NumExtendsInterfaces() > 0
? interface_declaration -> ExtendsInterface(interface_declaration -> NumExtendsInterfaces() - 1) -> RightToken()
: interface_declaration -> identifier_token),
inner_type -> ContainingPackage() -> PackageName(),
inner_type -> ExternalName());
}
else
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration;
ReportSemError(SemanticError::CIRCULAR_CLASS,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt
? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
inner_type -> ContainingPackage() -> PackageName(),
inner_type -> ExternalName());
}
}
}
//
// At this point the innertypes_closure set contains only the
// immediate inner types.
//
if (partially_ordered_types.Length() > 1) // inner_types set has more than one element?
{
SymbolSet &inner_types = *(type -> innertypes_closure);
assert(partially_ordered_types.Length() == inner_types.Size());
TopologicalSort *topological_sorter = new TopologicalSort(inner_types, partially_ordered_types);
topological_sorter -> Sort();
delete topological_sorter;
}
//
// Now, complete the closure set of inner types.
//
for (int i = 0; i < partially_ordered_types.Length(); i++)
{
TypeSymbol *inner_type = partially_ordered_types[i];
type -> AddNestedType(inner_type);
type -> innertypes_closure -> Union(*(inner_type -> innertypes_closure));
}
return;
}
void Semantic::ProcessTypeHeaders(AstClassDeclaration *class_declaration)
{
TypeSymbol *this_type = class_declaration -> semantic_environment -> Type();
assert(state_stack.Size() == 0 || this_type -> owner -> MethodCast()); // Not a nested type or a immediately local type.
ProcessTypeHeader(class_declaration);
ProcessNestedTypeHeaders(this_type, class_declaration -> class_body);
ProcessSuperTypesOfOuterType(this_type);
//
// Note that if we are processing an outermost type, no environment is set before we
// invoke ProcessTypeHeader to process its super types. Therefore, the dependence map
// is not updated with the super type information. In that case, we do so here.
//
if (state_stack.Size() == 0)
{
if (this_type -> super)
{
AddDependence(this_type,
this_type -> super,
(class_declaration -> super_opt ? class_declaration -> super_opt -> LeftToken()
: class_declaration -> identifier_token));
//
// Also, check whether or not the super type of this outermost type is accessible.
//
if (class_declaration -> super_opt)
{
state_stack.Push(this_type -> semantic_environment); // we need an environment for the type check.
TypeAccessCheck(class_declaration -> super_opt, this_type -> super);
state_stack.Pop();
}
}
for (int i = 0; i < class_declaration -> NumInterfaces(); i++)
{
if (class_declaration -> Interface(i) -> Type())
AddDependence(this_type,
class_declaration -> Interface(i) -> Type(),
class_declaration -> Interface(i) -> LeftToken());
}
}
return;
}
void Semantic::ProcessTypeHeaders(AstInterfaceDeclaration *interface_declaration)
{
TypeSymbol *this_type = interface_declaration -> semantic_environment -> Type();
assert(state_stack.Size() == 0); // Not a nested type
ProcessTypeHeader(interface_declaration);
ProcessNestedTypeHeaders(interface_declaration);
ProcessSuperTypesOfOuterType(interface_declaration -> semantic_environment -> Type());
//
// Note that no environment is set before we invoke ProcessTypeHeader to process the
// super types of this_type. As a result, the dependence map is not updated with tha
// information. We do so here.
//
for (int i = 0; i < interface_declaration -> NumExtendsInterfaces(); i++)
{
if (interface_declaration -> ExtendsInterface(i) -> Type())
AddDependence(this_type,
interface_declaration -> ExtendsInterface(i) -> Type(),
interface_declaration -> ExtendsInterface(i) -> LeftToken());
}
return;
}
void Semantic::ReportTypeInaccessible(LexStream::TokenIndex left_tok, LexStream::TokenIndex right_tok, TypeSymbol *type)
{
ReportSemError(SemanticError::TYPE_NOT_ACCESSIBLE,
left_tok,
right_tok,
type -> ContainingPackage() -> PackageName(),
type -> ExternalName(),
(type -> ACC_PRIVATE() ? StringConstant::US_private : (type -> ACC_PROTECTED() ? StringConstant::US_protected : StringConstant::US_default)));
return;
}
TypeSymbol *Semantic::FindNestedType(TypeSymbol *type, LexStream::TokenIndex identifier_token)
{
if (type == control.null_type || type == control.no_type || type -> Primitive())
return NULL;
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
if (! type -> expanded_type_table)
ComputeTypesClosure(type, identifier_token);
TypeShadowSymbol *type_shadow_symbol = type -> expanded_type_table -> FindTypeShadowSymbol(name_symbol);
return (type_shadow_symbol ? FindTypeInShadow(type_shadow_symbol, identifier_token)
: type -> FindTypeSymbol(name_symbol));
}
TypeSymbol *Semantic::MustFindNestedType(TypeSymbol *type, Ast *name)
{
AstSimpleName *simple_name = name -> SimpleNameCast();
LexStream::TokenIndex identifier_token = (simple_name ? simple_name -> identifier_token
: ((AstFieldAccess *) name) -> identifier_token);
TypeSymbol *inner_type = FindNestedType(type, identifier_token);
if (inner_type)
TypeAccessCheck(name, inner_type);
else inner_type = GetBadNestedType(type, identifier_token);
return inner_type;
}
//
// The Ast name is a qualified name (simple name or a field access). The function FindTypeInLayer
// searches for the first subname that is the name of a type contained in the set inner_types.
// If such a type is found, it is returned. Otherwise, the whole qualified name is resolved to
// a symbol that is returned.
//
TypeSymbol *Semantic::FindTypeInLayer(Ast *name, SymbolSet &inner_types)
{
//
// Unwind all the field accesses until we get to a base that is a simple name
//
Tuple<AstFieldAccess *> field;
for (AstFieldAccess *field_access = name -> FieldAccessCast(); field_access; field_access = field_access -> base -> FieldAccessCast())
{
field.Next() = field_access;
name = field_access -> base;
}
//
// If the simple_name base is a type that is an element in the inner_types set
// return it. Otherwise, assume it is a package name...
//
AstSimpleName *simple_name = name -> SimpleNameCast();
assert(simple_name);
PackageSymbol *package = NULL;
TypeSymbol *type = FindType(simple_name -> identifier_token);
if (type)
{
if (inner_types.IsElement(type))
return type;
}
else // If the simple_name is not a type, assume it is a package
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(simple_name -> identifier_token);
package = control.external_table.FindPackageSymbol(name_symbol);
if (! package)
package = control.external_table.InsertPackageSymbol(name_symbol, NULL);
control.FindPathsToDirectory(package);
}
//
// We now go through the field access in order until we either encouter a type that is an element of inner_types,
// in which case, we return the type. Otherwise, we return NULL.
//
//
for (int i = field.Length() - 1; i >= 0; i--)
{
AstFieldAccess *field_access = field[i];
if (type) // The base name is a type that is not contained in the inner_types set?
{
type = FindNestedType(type, field_access -> identifier_token); // resolve the next type...
if (! type)
break;
if (inner_types.IsElement(type))
return type;
}
else
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
type = package -> FindTypeSymbol(name_symbol);
if (! type)
{
FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
if (file_symbol)
type = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token);
}
else if (type -> SourcePending())
control.ProcessHeaders(type -> file_symbol);
//
//
//
if (type)
{
if (inner_types.IsElement(type))
return type;
}
else // If the field access was not resolved to a type assume it is a package
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol);
if (! subpackage)
subpackage = package -> InsertPackageSymbol(name_symbol);
control.FindPathsToDirectory(subpackage);
package = subpackage;
}
}
}
return NULL;
}
void Semantic::ProcessNestedSuperTypes(TypeSymbol *type)
{
int num_inner_types = type -> innertypes_closure -> Size();
if (num_inner_types > 0)
{
SymbolSet &inner_types = *(type -> innertypes_closure);
for (TypeSymbol *inner_type = (TypeSymbol *) inner_types.FirstElement();
inner_type;
inner_type = (TypeSymbol *) inner_types.NextElement())
{
if (inner_type -> ACC_INTERFACE())
{
AstInterfaceDeclaration *inner_interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration;
for (int l = 0; l < inner_interface_declaration -> NumExtendsInterfaces(); l++)
{
AstExpression *interface_name = inner_interface_declaration -> ExtendsInterface(l);
TypeSymbol *super_type = FindTypeInLayer(interface_name, inner_types);
if (super_type)
super_type -> subtypes -> AddElement(inner_type);
}
}
else
{
AstClassDeclaration *inner_class_declaration = (AstClassDeclaration *) inner_type -> declaration;
if (inner_class_declaration -> super_opt)
{
TypeSymbol *super_type = FindTypeInLayer(inner_class_declaration -> super_opt, inner_types);
if (super_type)
super_type -> subtypes -> AddElement(inner_type);
}
for (int l = 0; l < inner_class_declaration -> NumInterfaces(); l++)
{
TypeSymbol *super_type = FindTypeInLayer(inner_class_declaration -> Interface(l), inner_types);
if (super_type)
super_type -> subtypes -> AddElement(inner_type);
}
}
}
//
// Create a partial order or the inner types. If there are cycles,
// then the order is arbitrary.
//
Tuple<TypeSymbol *> partially_ordered_types;
if (num_inner_types > 0) // inner_types set is not empty?
{
TypeCycleChecker *cycle_checker = new TypeCycleChecker(partially_ordered_types);
cycle_checker -> PartialOrder(inner_types);
delete cycle_checker;
}
for (int k = 0; k < partially_ordered_types.Length(); k++)
{
TypeSymbol *inner_type = partially_ordered_types[k];
if (inner_type -> ACC_INTERFACE())
{
AstInterfaceDeclaration *inner_interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration;
ProcessTypeHeader(inner_interface_declaration);
ProcessNestedTypeHeaders(inner_interface_declaration);
}
else
{
AstClassDeclaration *inner_class_declaration = (AstClassDeclaration *) inner_type -> declaration;
ProcessTypeHeader(inner_class_declaration);
ProcessNestedTypeHeaders(inner_class_declaration -> semantic_environment -> Type(),
inner_class_declaration -> class_body);
}
}
ProcessSuperTypesOfInnerType(type, partially_ordered_types);
}
return;
}
void Semantic::ProcessNestedTypeHeaders(TypeSymbol *type, AstClassBody *class_body)
{
if (type -> expanded_type_table && (type -> super != control.Object() || type -> NumInterfaces() > 0))
{
delete type -> expanded_type_table;
type -> expanded_type_table = NULL;
}
if (! type -> expanded_type_table)
ComputeTypesClosure(type, class_body -> left_brace_token);
state_stack.Push(type -> semantic_environment);
type -> innertypes_closure = new SymbolSet;
for (int i = 0; i < class_body -> NumNestedClasses(); i++)
{
if (class_body -> NestedClass(i) -> semantic_environment)
type -> innertypes_closure -> AddElement(class_body -> NestedClass(i) -> semantic_environment -> Type());
}
for (int j = 0; j < class_body -> NumNestedInterfaces(); j++)
{
if (class_body -> NestedInterface(j) -> semantic_environment)
type -> innertypes_closure -> AddElement(class_body -> NestedInterface(j) -> semantic_environment -> Type());
}
ProcessNestedSuperTypes(type);
state_stack.Pop();
return;
}
void Semantic::ProcessNestedTypeHeaders(AstInterfaceDeclaration *interface_declaration)
{
TypeSymbol *type = interface_declaration -> semantic_environment -> Type();
if (type -> expanded_type_table && type -> NumInterfaces() > 0)
{
delete type -> expanded_type_table;
type -> expanded_type_table = NULL;
}
if (! type -> expanded_type_table)
ComputeTypesClosure(type, interface_declaration -> identifier_token);
state_stack.Push(interface_declaration -> semantic_environment);
type -> innertypes_closure = new SymbolSet;
for (int i = 0; i < interface_declaration -> NumNestedClasses(); i++)
{
if (interface_declaration -> NestedClass(i) -> semantic_environment)
type -> innertypes_closure -> AddElement(interface_declaration -> NestedClass(i) -> semantic_environment -> Type());
}
for (int j = 0; j < interface_declaration -> NumNestedInterfaces(); j++)
{
if (interface_declaration -> NestedInterface(j) -> semantic_environment)
type -> innertypes_closure -> AddElement(interface_declaration -> NestedInterface(j) -> semantic_environment -> Type());
}
ProcessNestedSuperTypes(type);
state_stack.Pop();
return;
}
//
// Pass 3: Process all method and constructor declarations within the compilation unit so that
// any field initialization enclosed in the compilation unit can invoke any constructor or
// method within the unit.
//
inline void Semantic::ProcessConstructorMembers(AstClassBody *class_body)
{
TypeSymbol *this_type = ThisType();
assert(this_type -> HeaderProcessed());
//
// If the class contains no constructor, ...
//
if (class_body -> NumConstructors() > 0)
{
for (int k = 0; k < class_body -> NumConstructors(); k++)
ProcessConstructorDeclaration(class_body -> Constructor(k));
}
else if (! this_type -> Anonymous())
AddDefaultConstructor(this_type);
this_type -> MarkConstructorMembersProcessed();
return;
}
inline void Semantic::ProcessMethodMembers(AstClassBody *class_body)
{
assert(ThisType() -> HeaderProcessed());
for (int k = 0; k < class_body -> NumMethods(); k++)
ProcessMethodDeclaration(class_body -> Method(k));
ThisType() -> MarkMethodMembersProcessed();
return;
}
inline void Semantic::ProcessFieldMembers(AstClassBody *class_body)
{
assert(ThisType() -> HeaderProcessed());
for (int i = 0; i < class_body -> NumInstanceVariables(); i++)
ProcessFieldDeclaration(class_body -> InstanceVariable(i));
for (int k = 0; k < class_body -> NumClassVariables(); k++)
ProcessFieldDeclaration(class_body -> ClassVariable(k));
ThisType() -> MarkFieldMembersProcessed();
return;
}
void Semantic::ProcessMembers(SemanticEnvironment *environment, AstClassBody *class_body)
{
//
//
//
state_stack.Push(environment);
TypeSymbol *this_type = ThisType();
assert(! this_type -> ConstructorMembersProcessed() || this_type -> Bad());
assert(! this_type -> MethodMembersProcessed() || this_type -> Bad());
assert(! this_type -> FieldMembersProcessed() || this_type -> Bad());
ProcessConstructorMembers(class_body);
ProcessMethodMembers(class_body);
ProcessFieldMembers(class_body);
delete this_type -> innertypes_closure; // save some space !!!
this_type -> innertypes_closure = NULL;
if (! this_type -> IsTopLevel())
{
for (int i = 0; i < class_body -> NumStaticInitializers(); i++)
{
ReportSemError(SemanticError::STATIC_INITIALIZER_IN_INNER_CLASS,
class_body -> StaticInitializer(i) -> LeftToken(),
class_body -> StaticInitializer(i) -> RightToken(),
this_type -> Name(),
this_type -> FileLoc());
}
}
for (int i = 0; i < this_type -> NumNestedTypes(); i++)
{
TypeSymbol *inner_type = this_type -> NestedType(i);
if (inner_type -> ACC_INTERFACE())
{
AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration;
ProcessMembers(interface_declaration);
if (! this_type -> IsTopLevel())
{
//
// TODO: 1.1 assumption
//
// As every field in an interface is static, we presume that all interfaces
// should be treated as static entities
//
if (interface_declaration -> semantic_environment)
{
ReportSemError(SemanticError::STATIC_TYPE_IN_INNER_CLASS,
interface_declaration -> identifier_token,
interface_declaration -> identifier_token,
lex_stream -> NameString(interface_declaration -> identifier_token),
this_type -> Name(),
this_type -> FileLoc());
}
}
}
else
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration;
ProcessMembers(class_declaration -> semantic_environment, class_declaration -> class_body);
if (! this_type -> IsTopLevel())
{
if (class_declaration -> semantic_environment && class_declaration -> semantic_environment -> Type() -> ACC_STATIC())
{
ReportSemError(SemanticError::STATIC_TYPE_IN_INNER_CLASS,
class_declaration -> identifier_token,
class_declaration -> identifier_token,
lex_stream -> NameString(class_declaration -> identifier_token),
this_type -> Name(),
this_type -> FileLoc());
}
}
}
}
state_stack.Pop();
return;
}
inline void Semantic::ProcessMethodMembers(AstInterfaceDeclaration *interface_declaration)
{
assert(ThisType() -> HeaderProcessed());
for (int k = 0; k < interface_declaration -> NumMethods(); k++)
ProcessMethodDeclaration(interface_declaration -> Method(k));
ThisType() -> MarkMethodMembersProcessed();
return;
}
inline void Semantic::ProcessFieldMembers(AstInterfaceDeclaration *interface_declaration)
{
assert(ThisType() -> HeaderProcessed());
for (int k = 0; k < interface_declaration -> NumClassVariables(); k++)
ProcessFieldDeclaration(interface_declaration -> ClassVariable(k));
ThisType() -> MarkFieldMembersProcessed();
return;
}
void Semantic::ProcessMembers(AstInterfaceDeclaration *interface_declaration)
{
//
//
//
state_stack.Push(interface_declaration -> semantic_environment);
TypeSymbol *this_type = ThisType();
assert(! this_type -> MethodMembersProcessed() || this_type -> Bad());
assert(! this_type -> FieldMembersProcessed() || this_type -> Bad());
ProcessMethodMembers(interface_declaration);
ProcessFieldMembers(interface_declaration);
delete this_type -> innertypes_closure; // save some space !!!
this_type -> innertypes_closure = NULL;
for (int i = 0; i < this_type -> NumNestedTypes(); i++)
{
TypeSymbol *inner_type = this_type -> NestedType(i);
if (inner_type -> ACC_INTERFACE())
{
AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) inner_type -> declaration;
ProcessMembers(interface_declaration);
}
else
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration;
ProcessMembers(class_declaration -> semantic_environment, class_declaration -> class_body);
}
}
state_stack.Pop();
return;
}
//
// Pass 4: Process the field declarations at the top level of the types
//
void Semantic::CompleteSymbolTable(SemanticEnvironment *environment, LexStream::TokenIndex identifier_token, AstClassBody *class_body)
{
if (compilation_unit -> BadCompilationUnitCast())
return;
state_stack.Push(environment);
TypeSymbol *this_type = ThisType();
assert(this_type -> ConstructorMembersProcessed());
assert(this_type -> MethodMembersProcessed());
assert(this_type -> FieldMembersProcessed());
//
//
//
if (! this_type -> expanded_method_table)
ComputeMethodsClosure(this_type, identifier_token);
ExpandedMethodTable &expanded_table = *(this_type -> expanded_method_table);
if (! this_type -> ACC_ABSTRACT())
{
//
// Check that every abstract method that is inherited is overridden.
//
for (int i = 0; i < expanded_table.symbol_pool.Length(); i++)
{
MethodSymbol *method = expanded_table.symbol_pool[i] -> method_symbol;
if (method -> ACC_ABSTRACT())
{
TypeSymbol *containing_type = method -> containing_type;
if (containing_type != this_type)
{
if (! method -> IsTyped())
method -> ProcessMethodSignature((Semantic *) this, identifier_token);
//
// If the method is contained in an abstract type read from a class file,
// then it is possible that the abstract method is just out-of-date and needs
// to be recompiled.
//
ReportSemError((! containing_type -> ACC_INTERFACE()) &&
(containing_type -> file_symbol && containing_type -> file_symbol -> IsClass())
? SemanticError::NON_ABSTRACT_TYPE_INHERITS_ABSTRACT_METHOD_FROM_ABSTRACT_CLASS
: SemanticError::NON_ABSTRACT_TYPE_INHERITS_ABSTRACT_METHOD,
identifier_token,
identifier_token,
method -> Header(),
containing_type -> ContainingPackage() -> PackageName(),
containing_type -> ExternalName(),
this_type -> ContainingPackage() -> PackageName(),
this_type -> ExternalName());
}
}
}
//
// If the super class of this_type is abstract and it is contained in a
// different package, check to see if its members include abstract methods
// with default access. If so, we must issue error messages for them also
// as they cannot be overridden.
//
if (this_type != control.Object() && this_type -> super -> ACC_ABSTRACT() &&
(this_type -> ContainingPackage() != this_type -> super -> ContainingPackage()))
{
ExpandedMethodTable &super_expanded_table = *(this_type -> super -> expanded_method_table);
for (int i = 0; i < super_expanded_table.symbol_pool.Length(); i++)
{
MethodSymbol *method = super_expanded_table.symbol_pool[i] -> method_symbol;
if (method -> ACC_ABSTRACT() &&
(! (method -> ACC_PUBLIC() || method -> ACC_PROTECTED() || method -> ACC_PRIVATE())))
{
TypeSymbol *containing_type = method -> containing_type;
if (! method -> IsTyped())
method -> ProcessMethodSignature((Semantic *) this, identifier_token);
//
// If the method is contained in an abstract type read from a class file,
// then it is possible that the abstract method is just out-of-date and needs
// to be recompiled.
//
ReportSemError(SemanticError::NON_ABSTRACT_TYPE_CANNOT_OVERRIDE_DEFAULT_ABSTRACT_METHOD,
identifier_token,
identifier_token,
method -> Header(),
containing_type -> ContainingPackage() -> PackageName(),
containing_type -> ExternalName(),
this_type -> ContainingPackage() -> PackageName(),
this_type -> ExternalName());
}
}
}
}
for (int i = 0; i < expanded_table.symbol_pool.Length(); i++)
{
MethodShadowSymbol *method_shadow = expanded_table.symbol_pool[i];
if (method_shadow -> NumConflicts() > 0)
{
MethodSymbol *method = method_shadow -> method_symbol;
if (method -> containing_type == this_type)
{
AstMethodDeclaration *method_declaration = (AstMethodDeclaration *) method -> method_or_constructor_declaration;
for (int k = 0; k < method_shadow -> NumConflicts(); k++)
{
MethodSymbol *hidden_method = method_shadow -> Conflict(k);
if (method -> containing_type != hidden_method -> containing_type) // the methods are not in the same type
CheckMethodOverride(method_declaration, hidden_method);
}
}
else
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) this_type -> declaration;
for (int k = 0; k < method_shadow -> NumConflicts(); k++)
{
MethodSymbol *hidden_method = method_shadow -> Conflict(k);
if (method -> containing_type != hidden_method -> containing_type) // the methods are not in the same type
CheckMethodOverride(class_declaration, method, hidden_method);
}
if (! method -> ACC_ABSTRACT())
{
if (method -> ACC_STATIC())
{
if (! method -> IsTyped())
method -> ProcessMethodSignature((Semantic *) this, identifier_token);
if (! method_shadow -> Conflict(0) -> IsTyped())
method_shadow -> Conflict(0) -> ProcessMethodSignature((Semantic *) this, identifier_token);
ReportSemError(SemanticError::STATIC_OVERRIDE_ABSTRACT_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
method_shadow -> Conflict(0) -> Header(),
method_shadow -> Conflict(0) -> containing_type -> ContainingPackage() -> PackageName(),
method_shadow -> Conflict(0) -> containing_type -> ExternalName());
}
}
}
method_shadow -> RemoveConflicts();
}
}
ProcessStaticInitializers(class_body);
ProcessBlockInitializers(class_body);
//
// Reset the this_variable and this_method may have been set in
// ProcessStaticInitializers and/or ProcessBlockInitializers.
// Indicate that there is no method being currently compiled
// in this environment.
//
ThisVariable() = NULL;
ThisMethod() = NULL;
//
// Recursively process all inner types
//
for (int l = 0; l < this_type -> NumNestedTypes(); l++)
{
TypeSymbol *inner_type = this_type -> NestedType(l);
if (inner_type -> ACC_INTERFACE())
CompleteSymbolTable((AstInterfaceDeclaration *) inner_type -> declaration);
else
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration;
CompleteSymbolTable(class_declaration -> semantic_environment,
class_declaration -> identifier_token, class_declaration -> class_body);
}
}
state_stack.Pop();
return;
}
void Semantic::CompleteSymbolTable(AstInterfaceDeclaration *interface_declaration)
{
if (compilation_unit -> BadCompilationUnitCast())
return;
state_stack.Push(interface_declaration -> semantic_environment);
TypeSymbol *this_type = ThisType();
assert(this_type -> MethodMembersProcessed());
assert(this_type -> FieldMembersProcessed());
//
//
//
if (! this_type -> expanded_method_table)
ComputeMethodsClosure(this_type, interface_declaration -> identifier_token);
ExpandedMethodTable &expanded_table = *(this_type -> expanded_method_table);
for (int i = 0; i < interface_declaration -> NumMethods(); i++)
{
AstMethodDeclaration *method_declaration = interface_declaration -> Method(i);
MethodSymbol *method = method_declaration -> method_symbol;
if (method)
{
MethodShadowSymbol *method_shadow = expanded_table.FindOverloadMethodShadow(method,
(Semantic *) this,
interface_declaration -> identifier_token);
for (int k = 0; k < method_shadow -> NumConflicts(); k++)
{
if (method_shadow -> method_symbol -> Type() != method_shadow -> Conflict(k) -> Type())
{
ReportSemError(SemanticError::MISMATCHED_INHERITED_METHOD,
method_declaration -> method_declarator -> LeftToken(),
method_declaration -> method_declarator -> RightToken(),
method_shadow -> method_symbol -> Header(),
method_shadow -> Conflict(k) -> Header(),
method_shadow -> Conflict(k) -> containing_type -> ContainingPackage() -> PackageName(),
method_shadow -> Conflict(k) -> containing_type -> ExternalName());
}
if (method_shadow -> method_symbol -> containing_type == this_type) // override ?
CheckInheritedMethodThrows(method_declaration, method_shadow -> Conflict(k));
}
}
}
//
// Compute the set of final variables (all fields in an interface are final) in this type.
//
Tuple<VariableSymbol *> finals(this_type -> NumVariableSymbols());
for (int j = 0; j < this_type -> NumVariableSymbols(); j++)
{
VariableSymbol *variable_symbol = this_type -> VariableSym(j);
finals.Next() = variable_symbol;
}
//
// Initialize each variable, in turn, and check to see if we need to declare a static initialization method: <clinit>.
//
MethodSymbol *init_method = NULL;
for (int k = 0; k < interface_declaration -> NumClassVariables(); k++)
{
InitializeVariable(interface_declaration -> ClassVariable(k), finals);
//
// We need a static constructor-initializer if we encounter at least one class
// variable that is declared with an initialization expression that is not a
// constant expression.
//
if ((! init_method) && NeedsInitializationMethod(interface_declaration -> ClassVariable(k)))
{
MethodSymbol *init_method = this_type -> InsertMethodSymbol(control.clinit_name_symbol);
init_method -> SetType(control.void_type);
init_method -> SetACC_FINAL();
init_method -> SetACC_STATIC();
init_method -> SetContainingType(this_type);
init_method -> SetBlockSymbol(new BlockSymbol(0)); // the symbol table associated with this block will contain no element
init_method -> block_symbol -> max_variable_index = 0;
init_method -> SetSignature(control);
//
//
//
init_method -> max_block_depth = 2; // TODO: Dave why is this the case? We need a legitimate comment here !!!
init_method -> block_symbol -> CompressSpace(); // space optimization
this_type -> static_initializer_method = init_method;
}
}
//
// Recursively process all inner types
//
for (int l = 0; l < this_type -> NumNestedTypes(); l++)
{
TypeSymbol *inner_type = this_type -> NestedType(l);
if (inner_type -> ACC_INTERFACE())
CompleteSymbolTable((AstInterfaceDeclaration *) inner_type -> declaration);
else
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) inner_type -> declaration;
CompleteSymbolTable(class_declaration -> semantic_environment,
class_declaration -> identifier_token, class_declaration -> class_body);
}
}
state_stack.Pop();
return;
}
//
// Pass 5: Free up unneeded space.
//
void Semantic::CleanUp()
{
if (control.option.nocleanup)
return;
for (int i = 0; i < compilation_unit -> NumTypeDeclarations(); i++)
{
TypeSymbol *type = NULL;
Ast *type_declaration = compilation_unit -> TypeDeclaration(i);
switch(type_declaration -> kind)
{
case Ast::CLASS:
{
AstClassDeclaration *class_declaration = (AstClassDeclaration *) type_declaration;
if (class_declaration -> semantic_environment)
type = class_declaration -> semantic_environment -> Type();
break;
}
case Ast::INTERFACE:
{
AstInterfaceDeclaration *interface_declaration = (AstInterfaceDeclaration *) type_declaration;
if (interface_declaration -> semantic_environment)
type = interface_declaration -> semantic_environment -> Type();
break;
}
case Ast::EMPTY_DECLARATION:
break;
default:
assert(false);
break;
}
if (type)
CleanUpType(type);
}
return;
}
void Semantic::CleanUpType(TypeSymbol *type)
{
type -> DeleteAnonymousTypes();
for (int i = 0; i < type -> NumNestedTypes(); i++)
CleanUpType(type -> NestedType(i));
type -> CompressSpace(); // space optimization
for (int j = 0; j < type -> NumMethodSymbols(); j++)
type -> MethodSym(j) -> CleanUp();
delete type -> local;
if (control.option.nocleanup)
return;
type -> local = NULL;
delete type -> non_local;
type -> non_local = NULL;
delete type -> semantic_environment;
type -> semantic_environment = NULL;
type -> declaration = NULL;
return;
}
TypeSymbol *Semantic::ReadType(FileSymbol *file_symbol, PackageSymbol *package, NameSymbol *name_symbol, LexStream::TokenIndex tok)
{
TypeSymbol *type;
if (file_symbol && file_symbol -> IsJava())
{
if (! file_symbol -> semantic)
control.ProcessHeaders(file_symbol);
type = package -> FindTypeSymbol(name_symbol);
if (! type)
{
type = package -> InsertOuterTypeSymbol(name_symbol);
type -> MarkBad();
type -> outermost_type = type;
type -> supertypes_closure = new SymbolSet;
type -> subtypes = new SymbolSet;
type -> semantic_environment = new SemanticEnvironment((Semantic *) this, type, NULL);
if (type != control.Object())
type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
type -> SetOwner(package);
type -> SetSignature(control);
AddDefaultConstructor(type);
type -> file_symbol = file_symbol;
file_symbol -> types.Next() = type;
ReportSemError(SemanticError::TYPE_NOT_FOUND,
tok,
tok,
type -> ContainingPackage() -> PackageName(),
type -> ExternalName());
}
}
else // Read class file.
{
type = package -> InsertOuterTypeSymbol(name_symbol);
type -> outermost_type = type;
type -> supertypes_closure = new SymbolSet;
type -> subtypes = new SymbolSet;
type -> SetOwner(package);
type -> SetSignature(control);
if (file_symbol)
{
type -> file_symbol = file_symbol;
type -> SetLocation();
file_symbol -> package = package;
file_symbol -> types.Next() = type;
ReadClassFile(type, tok);
assert (! type -> IsNested());
control.input_class_file_set.AddElement(file_symbol);
}
else
{
control.ProcessBadType(type);
type -> MarkBad();
if (type != control.Object())
type -> super = (type == control.Throwable() ? control.Object() : control.Throwable());
AddDefaultConstructor(type);
ReportSemError(SemanticError::TYPE_NOT_FOUND,
tok,
tok,
type -> ContainingPackage() -> PackageName(),
type -> ExternalName());
if (package == control.unnamed_package)
{
TypeSymbol *old_type = (TypeSymbol *) control.unnamed_package_types.Image(type -> Identity());
if (! old_type)
control.unnamed_package_types.AddElement(type);
else
{
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
tok,
tok,
type -> Name(),
old_type -> FileLoc());
}
}
}
}
return type;
}
TypeSymbol *Semantic::GetBadNestedType(TypeSymbol *type, LexStream::TokenIndex identifier_token)
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
TypeSymbol *outermost_type = type -> outermost_type;
if (! outermost_type -> non_local)
outermost_type -> non_local = new SymbolSet;
if (! outermost_type -> local)
outermost_type -> local = new SymbolSet;
int length = type -> ExternalNameLength() + 1 + name_symbol -> NameLength(); // +1 for $,... +1 for $
wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(external_name, type -> ExternalName());
wcscat(external_name, StringConstant::US__DS);
wcscat(external_name, name_symbol -> Name());
TypeSymbol *inner_type = type -> InsertNestedTypeSymbol(name_symbol);
inner_type -> MarkBad();
inner_type -> outermost_type = type -> outermost_type;
inner_type -> supertypes_closure = new SymbolSet;
inner_type -> subtypes = new SymbolSet;
inner_type -> SetExternalIdentity(control.FindOrInsertName(external_name, length));
inner_type -> semantic_environment = new SemanticEnvironment((Semantic *) this,
inner_type,
type -> semantic_environment);
inner_type -> super = control.Object();
inner_type -> SetOwner(type);
inner_type -> SetSignature(control);
inner_type -> InsertThis(0);
AddDefaultConstructor(inner_type);
ReportSemError(SemanticError::TYPE_NOT_FOUND,
identifier_token,
identifier_token,
inner_type -> ContainingPackage() -> PackageName(),
inner_type -> ExternalName());
delete [] external_name;
return inner_type;
}
void Semantic::ProcessImportQualifiedName(AstExpression *name)
{
AstFieldAccess *field_access = name -> FieldAccessCast();
if (field_access)
{
ProcessImportQualifiedName(field_access -> base);
Symbol *symbol = field_access -> base -> symbol;
TypeSymbol *type = symbol -> TypeCast();
if (type) // The base name is a type
{
if (! type -> NestedTypesProcessed())
type -> ProcessNestedTypeSignatures((Semantic *) this, field_access -> identifier_token);
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
TypeSymbol *inner_type = type -> FindTypeSymbol(name_symbol);
if (! inner_type)
inner_type = GetBadNestedType(type, field_access -> identifier_token);
else if (! (inner_type -> ACC_PUBLIC() || inner_type -> ContainingPackage() == this_package))
ReportTypeInaccessible(field_access, inner_type);
type = inner_type;
field_access -> symbol = type; // save the type to which this expression was resolved for later use...
}
else
{
PackageSymbol *package = symbol -> PackageCast();
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
type = package -> FindTypeSymbol(name_symbol);
if (! type)
{
FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
if (file_symbol)
type = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token);
}
else if (type -> SourcePending())
control.ProcessHeaders(type -> file_symbol);
//
// If the field_access was resolved to a type, save it later use.
// Otherwise, assume the field_access is a package name.
//
if (type)
field_access -> symbol = type;
else
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol);
if (! subpackage)
subpackage = package -> InsertPackageSymbol(name_symbol);
control.FindPathsToDirectory(subpackage);
field_access -> symbol = subpackage;
}
}
}
else
{
AstSimpleName *simple_name = name -> SimpleNameCast();
assert(simple_name);
//
// From the 1.1 document:
//
// Nested classes of all sorts (top-level or inner) can be imported by either kind of
// import statement. Class names in import statements must be fully package
// qualified, and be resolvable without reference to inheritance relations...
//
TypeSymbol *type;
if (compilation_unit -> package_declaration_opt)
{
type = FindSimpleNameType(this_package, simple_name -> identifier_token);
//
// If the type was not found, look for it in the unnamed package.
// The relevant passages that justify this lookup are:
// 6.5.4.11, 6.7, 7.4.2, 7.5.1
//
if (! type)
type = FindSimpleNameType(control.unnamed_package, simple_name -> identifier_token);
}
else type = FindSimpleNameType(control.unnamed_package, simple_name -> identifier_token);
//
// If the simple_name is a type, save it. Otherwise, assume it is a package
//
if (type)
{
if (! (type -> ACC_PUBLIC() || type -> ContainingPackage() == this_package))
ReportTypeInaccessible(name, type);
simple_name -> symbol = type;
}
else
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(simple_name -> identifier_token);
PackageSymbol *package = control.external_table.FindPackageSymbol(name_symbol);
if (! package)
package = control.external_table.InsertPackageSymbol(name_symbol, NULL);
control.FindPathsToDirectory(package);
simple_name -> symbol = package;
}
}
return;
}
void Semantic::ProcessPackageOrType(AstExpression *name)
{
AstFieldAccess *field_access = name -> FieldAccessCast();
if (field_access)
{
ProcessPackageOrType(field_access -> base);
Symbol *symbol = field_access -> base -> symbol;
TypeSymbol *type = symbol -> TypeCast();
if (type) // The base name is a type
{
type = MustFindNestedType(type, field_access);
field_access -> symbol = type; // save the type to which this expression was resolved for later use...
}
else
{
PackageSymbol *package = symbol -> PackageCast();
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
type = package -> FindTypeSymbol(name_symbol);
if (! type)
{
FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
if (file_symbol)
type = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token);
}
else if (type -> SourcePending())
control.ProcessHeaders(type -> file_symbol);
//
// If the field access was resolved into a type, then save it.
// Otherwise, assume it is a package
//
if (type)
field_access -> symbol = type; // save the type to which this expression was resolved for later use...
else
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol);
if (! subpackage)
subpackage = package -> InsertPackageSymbol(name_symbol);
control.FindPathsToDirectory(subpackage);
field_access -> symbol = subpackage;
}
}
}
else
{
AstSimpleName *simple_name = name -> SimpleNameCast();
assert(simple_name);
TypeSymbol *type = FindType(simple_name -> identifier_token);
if (type)
{
TypeAccessCheck(simple_name, type);
simple_name -> symbol = type;
}
else
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(simple_name -> identifier_token);
PackageSymbol *package = control.external_table.FindPackageSymbol(name_symbol);
if (! package)
package = control.external_table.InsertPackageSymbol(name_symbol, NULL);
control.FindPathsToDirectory(package);
simple_name -> symbol = package;
}
}
return;
}
void Semantic::ProcessTypeImportOnDemandDeclaration(AstImportDeclaration *import_declaration)
{
ProcessImportQualifiedName(import_declaration -> name);
Symbol *symbol = import_declaration -> name -> symbol;
PackageSymbol *package = symbol -> PackageCast();
if (package && package -> directory.Length() == 0)
{
ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
import_declaration -> name -> LeftToken(),
import_declaration -> name -> RightToken(),
package -> PackageName());
}
//
// Two or more type-import-on-demand may name the same package; the effect is as if there
// were only one such declaration.
//
for (int i = 0; i < import_on_demand_packages.Length(); i++)
{
if (symbol == import_on_demand_packages[i])
return;
}
import_on_demand_packages.Next() = symbol;
//
//
//
TypeSymbol *type = symbol -> TypeCast();
if (control.option.deprecation && type && type -> IsDeprecated() && type -> file_symbol != source_file_symbol)
{
ReportSemError(SemanticError::DEPRECATED_TYPE,
import_declaration -> name -> LeftToken(),
import_declaration -> name -> RightToken(),
type -> ContainingPackage() -> PackageName(),
type -> ExternalName());
}
return;
}
//
// The Ast name is a name expression (either a qualified name or a simplename)
// FindFirstType traverses the name tree and returns the first subtree that it
// finds that matches a type. As a side-effect, each subtree that matches a package
// or a type has that package or type recorded in its "symbol" field.
//
AstExpression *Semantic::FindFirstType(Ast *name)
{
AstExpression *name_expression = NULL;
AstFieldAccess *field_access = name -> FieldAccessCast();
if (field_access)
{
AstExpression *expr = FindFirstType(field_access -> base);
if (expr -> symbol -> TypeCast()) // A subexpression has been found, pass it up
name_expression = expr;
else
{
PackageSymbol *package = expr -> symbol -> PackageCast();
assert(package);
name_expression = field_access; // The relevant subexpression might be this field access...
NameSymbol *name_symbol = lex_stream -> NameSymbol(field_access -> identifier_token);
TypeSymbol *type = package -> FindTypeSymbol(name_symbol);
if (type)
{
if (type -> SourcePending())
control.ProcessHeaders(type -> file_symbol);
field_access -> symbol = type;
}
else
{
FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
if (file_symbol)
field_access -> symbol = ReadType(file_symbol, package, name_symbol, field_access -> identifier_token);
else
{
PackageSymbol *subpackage = package -> FindPackageSymbol(name_symbol);
if (! subpackage)
subpackage = package -> InsertPackageSymbol(name_symbol);
control.FindPathsToDirectory(subpackage);
field_access -> symbol = subpackage;
}
}
}
}
else
{
AstSimpleName *simple_name = name -> SimpleNameCast();
assert(simple_name);
ProcessPackageOrType(simple_name);
name_expression = simple_name;
}
return name_expression;
}
TypeSymbol *Semantic::FindSimpleNameType(PackageSymbol *package, LexStream::TokenIndex identifier_token)
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
TypeSymbol *type = package -> FindTypeSymbol(name_symbol);
if (type)
{
if (type -> SourcePending())
control.ProcessHeaders(type -> file_symbol);
}
else
{
//
// Check whether or not the type was declared in another compilation unit
// in the main package.
//
FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
if (file_symbol)
type = ReadType(file_symbol, package, name_symbol, identifier_token);
}
return type;
}
void Semantic::ProcessSingleTypeImportDeclaration(AstImportDeclaration *import_declaration)
{
ProcessImportQualifiedName(import_declaration -> name);
Symbol *symbol = import_declaration -> name -> symbol;
PackageSymbol *package = symbol -> PackageCast();
if (package)
{
ReportSemError(SemanticError::UNKNOWN_QUALIFIED_NAME_BASE,
import_declaration -> name -> LeftToken(),
import_declaration -> name -> RightToken(),
package -> PackageName());
return;
}
TypeSymbol *type = symbol -> TypeCast();
//
// If two single-type-import declarations in the same compilation unit attempt to
// import types with the same simple name, then a compile-time error occurs, unless
// the two types are the same type, in which case the duplicate declaration is ignored.
//
for (int i = 0; i < single_type_imports.Length(); i++)
{
if (type == single_type_imports[i])
return;
}
TypeSymbol *old_type;
int k;
for (k = 0; k < compilation_unit -> NumTypeDeclarations(); k++)
{
AstClassDeclaration *class_declaration = compilation_unit -> TypeDeclaration(k) -> ClassDeclarationCast();
AstInterfaceDeclaration *interface_declaration = compilation_unit -> TypeDeclaration(k) -> InterfaceDeclarationCast();
if (class_declaration)
{
if (class_declaration -> semantic_environment)
{
old_type = class_declaration -> semantic_environment -> Type();
if (old_type -> Identity() == type -> Identity())
break;
}
}
else if (interface_declaration)
{
if (interface_declaration -> semantic_environment)
{
old_type = interface_declaration -> semantic_environment -> Type();
if (old_type -> Identity() == type -> Identity())
break;
}
}
}
if (k < compilation_unit -> NumTypeDeclarations())
{
AstFieldAccess *field_access = import_declaration -> name -> FieldAccessCast();
package = (field_access ? field_access -> base -> symbol -> PackageCast() : control.unnamed_package);
//
// It's ok to import a type that is being compiled...
//
if (type == old_type && package == this_package)
{
ReportSemError(SemanticError::UNNECESSARY_TYPE_IMPORT,
import_declaration -> name -> LeftToken(),
import_declaration -> name -> RightToken(),
lex_stream -> NameString(import_declaration -> name -> RightToken()),
old_type -> FileLoc());
}
else
{
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
import_declaration -> name -> LeftToken(),
import_declaration -> name -> RightToken(),
lex_stream -> NameString(import_declaration -> name -> RightToken()),
old_type -> FileLoc());
}
}
else
{
int i = 0;
for (i = 0; i < compilation_unit -> NumImportDeclarations(); i++)
{
TypeSymbol *other_type = compilation_unit -> ImportDeclaration(i) -> name -> Type();
if ((compilation_unit -> ImportDeclaration(i) == import_declaration) ||
(other_type && other_type -> Identity() == type -> Identity()))
break;
}
assert(i < compilation_unit -> NumImportDeclarations());
if (compilation_unit -> ImportDeclaration(i) == import_declaration) // No duplicate found
{
import_declaration -> name -> symbol = type;
single_type_imports.Next() = type;
}
else
{
FileLocation file_location(lex_stream, compilation_unit -> ImportDeclaration(i) -> LeftToken());
ReportSemError(SemanticError::DUPLICATE_TYPE_DECLARATION,
import_declaration -> name -> LeftToken(),
import_declaration -> name -> RightToken(),
lex_stream -> NameString(import_declaration -> name -> RightToken()),
file_location.location);
}
}
if (! (type -> ACC_PUBLIC() || type -> ContainingPackage() == this_package))
ReportTypeInaccessible(import_declaration -> name, type);
//
//
//
if (control.option.deprecation && type -> IsDeprecated() && type -> file_symbol != source_file_symbol)
{
ReportSemError(SemanticError::DEPRECATED_TYPE,
import_declaration -> name -> LeftToken(),
import_declaration -> name -> RightToken(),
type -> ContainingPackage() -> PackageName(),
type -> ExternalName());
}
return;
}
void Semantic::ProcessFieldDeclaration(AstFieldDeclaration *field_declaration)
{
TypeSymbol *this_type = ThisType();
AccessFlags access_flags = (this_type -> ACC_INTERFACE()
? ProcessConstantModifiers(field_declaration)
: ProcessFieldModifiers(field_declaration));
//
// New feature in java 1.2 that is undocumented in the 1.1 document.
// A field may be declared static iff it is final and not blank-final...
//
if (access_flags.ACC_STATIC() && (! access_flags.ACC_FINAL()) && this_type -> IsInner())
{
AstModifier *modifier = NULL;
for (int i = 0; i < field_declaration -> NumVariableModifiers(); i++)
{
if (field_declaration -> VariableModifier(i) -> kind == Ast::STATIC)
modifier = field_declaration -> VariableModifier(i);
}
assert(modifier);
ReportSemError(SemanticError::STATIC_FIELD_IN_INNER_CLASS,
modifier -> modifier_kind_token,
modifier -> modifier_kind_token);
}
//
//
//
bool deprecated_declarations = lex_stream -> IsDeprecated(lex_stream -> Previous(field_declaration -> LeftToken()));
AstArrayType *array_type = field_declaration -> type -> ArrayTypeCast();
Ast *actual_type = (array_type ? array_type -> type : field_declaration -> type);
AstPrimitiveType *primitive_type = actual_type -> PrimitiveTypeCast();
TypeSymbol *field_type = (primitive_type ? FindPrimitiveType(primitive_type) : MustFindType(actual_type));
for (int i = 0; i < field_declaration -> NumVariableDeclarators(); i++)
{
AstVariableDeclarator *variable_declarator = field_declaration -> VariableDeclarator(i);
AstVariableDeclaratorId *name = variable_declarator -> variable_declarator_name;
NameSymbol *name_symbol = lex_stream -> NameSymbol(name -> identifier_token);
if (this_type -> FindVariableSymbol(name_symbol))
{
ReportSemError(SemanticError::DUPLICATE_FIELD,
name -> identifier_token,
name -> identifier_token,
name_symbol -> Name(),
this_type -> Name());
}
else
{
VariableSymbol *variable = this_type -> InsertVariableSymbol(name_symbol);
int num_dimensions = (array_type ? array_type -> NumBrackets() : 0) + name -> NumBrackets();
if (num_dimensions == 0)
variable -> SetType(field_type);
else variable -> SetType(field_type -> GetArrayType((Semantic *) this, num_dimensions));
variable -> SetFlags(access_flags);
variable -> SetOwner(this_type);
variable -> declarator = variable_declarator;
variable -> MarkIncomplete(); // the declaration of a field is not complete until its initializer
// (if any) has been processed.
variable_declarator -> symbol = variable;
if (deprecated_declarations)
variable -> MarkDeprecated();
}
}
return;
}
void Semantic::GenerateLocalConstructor(MethodSymbol *constructor)
{
TypeSymbol *local_type = constructor -> containing_type;
//
// Make up external name for constructor as we shall turn it into a regular method later.
// Note that the method needs to be PRIVATE and FINAL so that:
//
// 1. virtual calls are not made to it
//
// 2. it might be inlined later.
//
// This resetting destroys the original access flags specified by the user. We shall
// say more about this later...
//
IntToWstring value(local_type -> NumGeneratedConstructors());
int length = 12 + value.Length(); // +12 for constructor$
wchar_t *external_name = new wchar_t[length + 1]; // +1 for '\0';
wcscpy(external_name, StringConstant::US__constructor_DOLLAR);
wcscat(external_name, value.String());
constructor -> SetExternalIdentity(control.FindOrInsertName(external_name, length)); // Turn the constructor into a method
constructor -> ResetFlags();
constructor -> SetACC_PRIVATE();
constructor -> SetACC_FINAL();
delete [] external_name;
//
// Make generated constructor symbol. The associated symbol table will not contain too many elements.
//
BlockSymbol *block_symbol = new BlockSymbol(local_type -> NumConstructorParameters() +
constructor -> NumFormalParameters() + 3);
block_symbol -> max_variable_index = 1; // All types need a spot for "this"
//
// Note that the local constructor does not inherit the access flags of the specified constructor.
// This is because it acts more like a read_access method. The synthetic attribute that is associated
// with the constructor allows the compiler to prevent an illegal access from an unauthorized environment.
//
MethodSymbol *local_constructor = local_type -> LocalConstructorOverload(constructor);
local_constructor -> MarkSynthetic();
local_constructor -> method_or_constructor_declaration = constructor -> method_or_constructor_declaration;
local_constructor -> SetType(control.void_type);
local_constructor -> SetContainingType(local_type);
local_constructor -> SetBlockSymbol(block_symbol);
for (int i = 0; i < constructor -> NumThrows(); i++)
local_constructor -> AddThrows(constructor -> Throws(i));
for (int j = 0; j < local_type -> NumConstructorParameters(); j++)
{
VariableSymbol *param = local_type -> ConstructorParameter(j),
*symbol = block_symbol -> InsertVariableSymbol(param -> Identity());
symbol -> MarkSynthetic();
symbol -> SetType(param -> Type());
symbol -> SetOwner(local_constructor);
symbol -> SetExternalIdentity(param -> ExternalIdentity());
symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
if (control.IsDoubleWordType(symbol -> Type()))
block_symbol -> max_variable_index++;
local_constructor -> AddFormalParameter(symbol);
}
//
// Add all the parameters from the original constructor to the symbol
// table of the local constructor. However, only mark them complete and
// do not yet assign a number to them. This will be done after we know
// how many extra "local" variable shadows are needed.
//
for (int k = 0; k < constructor -> NumFormalParameters(); k++)
{
VariableSymbol *param = constructor -> FormalParameter(k),
*symbol = block_symbol -> InsertVariableSymbol(param -> Identity());
symbol -> MarkSynthetic();
symbol -> MarkComplete();
symbol -> SetType(param -> Type());
symbol -> SetOwner(local_constructor);
}
local_type -> AddGeneratedConstructor(local_constructor);
return;
}
void Semantic::ProcessConstructorDeclaration(AstConstructorDeclaration *constructor_declaration)
{
TypeSymbol *this_type = ThisType();
if (this_type -> Anonymous())
{
ReportSemError(SemanticError::CONSTRUCTOR_FOUND_IN_ANONYMOUS_CLASS,
constructor_declaration -> LeftToken(),
constructor_declaration -> RightToken());
return;
}
AccessFlags access_flags = ProcessConstructorModifiers(constructor_declaration);
AstMethodDeclarator *constructor_declarator = constructor_declaration -> constructor_declarator;
wchar_t *constructor_name = lex_stream -> NameString(constructor_declarator -> identifier_token);
if (lex_stream -> NameSymbol(constructor_declarator -> identifier_token) != this_type -> Identity())
{
ReportSemError(SemanticError::MISMATCHED_CONSTRUCTOR_NAME,
constructor_declarator -> identifier_token,
constructor_declarator -> identifier_token,
constructor_name,
this_type -> Name());
constructor_name = this_type -> Name(); // assume the proper name !
}
//
// As the body of the constructor may not have been parsed yet, we estimate a size
// for its symbol table based on the number of lines in the body + a margin for one-liners.
//
BlockSymbol *block_symbol = new BlockSymbol(constructor_declarator -> NumFormalParameters() + 3);
block_symbol -> max_variable_index = 1; // All types need a spot for "this".
ProcessFormalParameters(block_symbol, constructor_declarator);
//
// Note that constructors are always named "<init>"
//
MethodSymbol *constructor = this_type -> FindMethodSymbol(control.init_name_symbol);
if (! constructor) // there exists a constructor already in type -> table.
constructor = this_type -> InsertConstructorSymbol(control.init_name_symbol);
else
{
if (this_type -> FindOverloadMethod(constructor, constructor_declarator))
{
ReportSemError(SemanticError::DUPLICATE_CONSTRUCTOR,
constructor_declarator -> LeftToken(),
constructor_declarator -> RightToken(),
this_type -> Name());
delete block_symbol;
return;
}
constructor = this_type -> Overload(constructor);
}
//
// If the method is not static, leave a slot for the "this" pointer.
//
constructor -> SetType(control.void_type);
constructor -> SetFlags(access_flags);
constructor -> SetContainingType(this_type);
constructor -> SetBlockSymbol(block_symbol);
constructor -> method_or_constructor_declaration = constructor_declaration;
VariableSymbol *this0_variable = NULL;
if (this_type -> IsInner())
{
this0_variable = block_symbol -> InsertVariableSymbol(control.this0_name_symbol);
this0_variable -> SetType(this_type -> ContainingType());
this0_variable -> SetOwner(constructor);
this0_variable -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
}
for (int i = 0; i < constructor_declarator -> NumFormalParameters(); i++)
{
AstVariableDeclarator *formal_declarator = constructor_declarator -> FormalParameter(i) -> formal_declarator;
VariableSymbol *symbol = formal_declarator -> symbol;
symbol -> SetOwner(constructor);
symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
if (control.IsDoubleWordType(symbol -> Type()))
block_symbol -> max_variable_index++;
symbol -> declarator = formal_declarator;
constructor -> AddFormalParameter(symbol);
}
constructor -> SetSignature(control, this0_variable);
for (int k = 0; k < constructor_declaration -> NumThrows(); k++)
{
AstExpression *throw_expression = constructor_declaration -> Throw(k);
TypeSymbol *throw_type = MustFindType(throw_expression);
throw_expression -> symbol = throw_type;
constructor -> AddThrows(throw_type);
}
constructor_declaration -> constructor_symbol = constructor; // save for processing bodies later.
if (this_type -> IsLocal())
GenerateLocalConstructor(constructor);
if (lex_stream -> IsDeprecated(lex_stream -> Previous(constructor_declaration -> LeftToken())))
constructor -> MarkDeprecated();
return;
}
void Semantic::AddDefaultConstructor(TypeSymbol *type)
{
MethodSymbol *constructor = type -> InsertConstructorSymbol(control.init_name_symbol);
BlockSymbol *block_symbol = new BlockSymbol(1); // TODO: make sure this size is right !!!
block_symbol -> max_variable_index = 1; // All types need a spot for "this"
constructor -> SetType(control.void_type);
constructor -> SetContainingType(type);
constructor -> SetBlockSymbol(block_symbol);
if (type -> ACC_PUBLIC())
constructor -> SetACC_PUBLIC();
VariableSymbol *this0_variable = NULL;
if (type -> IsInner())
{
this0_variable = block_symbol -> InsertVariableSymbol(control.this0_name_symbol);
this0_variable -> SetType(type -> ContainingType());
this0_variable -> SetOwner(constructor);
this0_variable -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
}
constructor -> SetSignature(control, this0_variable);
AstClassDeclaration *class_declaration = (type -> declaration ? type -> declaration -> ClassDeclarationCast()
: (AstClassDeclaration *) NULL);
if (class_declaration)
{
AstClassBody *class_body = class_declaration -> class_body;
LexStream::TokenIndex left_loc = class_declaration -> identifier_token,
right_loc = (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token);
AstMethodDeclarator *method_declarator = compilation_unit -> ast_pool -> GenMethodDeclarator();
method_declarator -> identifier_token = left_loc;
method_declarator -> left_parenthesis_token = left_loc;
method_declarator -> right_parenthesis_token = right_loc;
AstSuperCall *super_call = NULL;
if (type != control.Object())
{
super_call = compilation_unit -> ast_pool -> GenSuperCall();
super_call -> base_opt = NULL;
super_call -> dot_token_opt = 0;
super_call -> super_token = left_loc;
super_call -> left_parenthesis_token = left_loc;
super_call -> right_parenthesis_token = right_loc;
super_call -> semicolon_token = right_loc;
}
AstReturnStatement *return_statement = compilation_unit -> ast_pool -> GenReturnStatement();
return_statement -> return_token = left_loc;
return_statement -> expression_opt = NULL;
return_statement -> semicolon_token = left_loc;
return_statement -> is_reachable = true;
AstBlock *block = compilation_unit -> ast_pool -> GenBlock();
block -> AllocateBlockStatements(1); // this block contains one statement
block -> left_brace_token = left_loc;
block -> right_brace_token = right_loc;
block -> is_reachable = true;
block -> can_complete_normally = false;
block -> AddStatement(return_statement);
AstConstructorBlock *constructor_block = compilation_unit -> ast_pool -> GenConstructorBlock();
constructor_block -> left_brace_token = left_loc;
constructor_block -> explicit_constructor_invocation_opt = super_call;
constructor_block -> block = block;
constructor_block -> right_brace_token = right_loc;
AstConstructorDeclaration *constructor_declaration = compilation_unit -> ast_pool -> GenConstructorDeclaration();
constructor_declaration -> constructor_declarator = method_declarator;
constructor_declaration -> constructor_body = constructor_block;
constructor_declaration -> constructor_symbol = constructor;
constructor -> method_or_constructor_declaration = constructor_declaration;
class_body -> default_constructor = constructor_declaration;
if (type -> IsLocal())
GenerateLocalConstructor(constructor);
}
return;
}
void Semantic::CheckInheritedMethodThrows(AstMethodDeclaration *method_declaration, MethodSymbol *method)
{
if (method_declaration -> NumThrows() > 0)
{
if (! method -> IsTyped())
method -> ProcessMethodSignature((Semantic *) this, method_declaration -> Throw(0) -> LeftToken());
method -> ProcessMethodThrows((Semantic *) this, method_declaration -> Throw(0) -> LeftToken());
for (int i = 0; i < method_declaration -> NumThrows(); i++)
{
AstExpression *name = method_declaration -> Throw(i);
TypeSymbol *exception = (TypeSymbol *) name -> symbol;
if (CheckedException(exception))
{
int k;
for (k = method -> NumThrows() - 1; k >= 0; k--)
{
if (exception -> IsSubclass(method -> Throws(k)))
break;
}
if (k < 0)
{
ReportSemError(SemanticError::MISMATCHED_OVERRIDDEN_EXCEPTION,
name -> LeftToken(),
name -> RightToken(),
exception -> Name(),
method -> Header(),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName());
}
}
}
}
return;
}
void Semantic::CheckMethodOverride(AstMethodDeclaration *method_declaration, MethodSymbol *hidden_method)
{
AstMethodDeclarator *method_declarator = method_declaration -> method_declarator;
MethodSymbol *method = method_declaration -> method_symbol;
if (hidden_method -> Type() != method -> Type())
{
ReportSemError(SemanticError::MISMATCHED_INHERITED_METHOD,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
method -> Header(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
if (hidden_method -> IsFinal() || hidden_method -> ACC_PRIVATE()) // Merged because same kind of message. See error.cpp
ReportSemError(hidden_method -> IsFinal() ? SemanticError::FINAL_METHOD_OVERRIDE : SemanticError::PRIVATE_METHOD_OVERRIDE,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
method -> Header(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
if (method -> ACC_STATIC() != hidden_method -> ACC_STATIC())
{
if (method -> ACC_STATIC())
ReportSemError(SemanticError::INSTANCE_METHOD_OVERRIDE,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
method -> Header(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
else ReportSemError(SemanticError::CLASS_METHOD_OVERRIDE,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
method -> Header(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
if (hidden_method -> ACC_PUBLIC())
{
if (! method -> ACC_PUBLIC())
ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
method -> Header(),
(method -> ACC_PRIVATE() ? StringConstant::US_private : (method -> ACC_PROTECTED() ? StringConstant::US_protected : StringConstant::US_default)),
hidden_method -> Header(),
StringConstant::US_public,
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
else if (hidden_method -> ACC_PROTECTED())
{
if (! (method -> ACC_PROTECTED() || method -> ACC_PUBLIC()))
ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
method -> Header(),
StringConstant::US_default,
hidden_method -> Header(),
StringConstant::US_protected,
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
else if (method -> ACC_PRIVATE()) // The hidden_method method must have default access as it cannot be private...
{
ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
method -> Header(),
StringConstant::US_private,
hidden_method -> Header(),
StringConstant::US_default,
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
CheckInheritedMethodThrows(method_declaration, hidden_method);
return;
}
void Semantic::CheckInheritedMethodThrows(AstClassDeclaration *class_declaration, MethodSymbol *method, MethodSymbol *hidden_method)
{
method -> ProcessMethodThrows((Semantic *) this, class_declaration -> identifier_token);
hidden_method -> ProcessMethodThrows((Semantic *) this, class_declaration -> identifier_token);
for (int i = method -> NumThrows() - 1; i >= 0; i--)
{
TypeSymbol *exception = method -> Throws(i);
if (CheckedException(exception))
{
int k;
for (k = hidden_method -> NumThrows() - 1; k >= 0; k--)
{
if (exception -> IsSubclass(hidden_method -> Throws(k)))
break;
}
if (k < 0)
{
if (! method -> IsTyped())
method -> ProcessMethodSignature((Semantic *) this, class_declaration -> identifier_token);
if (! hidden_method -> IsTyped())
hidden_method -> ProcessMethodSignature((Semantic *) this, class_declaration -> identifier_token);
ReportSemError(SemanticError::MISMATCHED_OVERRIDDEN_EXCEPTION_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
exception -> Name(),
method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName(),
hidden_method -> Header(),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName());
}
}
}
return;
}
void Semantic::CheckMethodOverride(AstClassDeclaration *class_declaration, MethodSymbol *method, MethodSymbol *hidden_method)
{
if (hidden_method -> Type() != method -> Type())
ReportSemError(SemanticError::MISMATCHED_INHERITED_METHOD_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
if (hidden_method -> IsFinal() || hidden_method -> ACC_PRIVATE()) // Merged because same kind of message. See error.cpp
ReportSemError(hidden_method -> IsFinal() ? SemanticError::FINAL_METHOD_OVERRIDE_EXTERNALLY
: SemanticError::PRIVATE_METHOD_OVERRIDE_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
if (method -> ACC_STATIC() != hidden_method -> ACC_STATIC())
{
if (method -> ACC_STATIC())
ReportSemError(SemanticError::INSTANCE_METHOD_OVERRIDE_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
else ReportSemError(SemanticError::CLASS_METHOD_OVERRIDE_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
hidden_method -> Header(),
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
if (hidden_method -> ACC_PUBLIC())
{
if (! method -> ACC_PUBLIC())
ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
(method -> ACC_PRIVATE() ? StringConstant::US_private
: (method -> ACC_PROTECTED() ? StringConstant::US_protected
: StringConstant::US_default)),
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
hidden_method -> Header(),
StringConstant::US_public,
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
else if (hidden_method -> ACC_PROTECTED())
{
if (! (method -> ACC_PROTECTED() || method -> ACC_PUBLIC()))
ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
StringConstant::US_default,
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
hidden_method -> Header(),
StringConstant::US_protected,
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
else if (method -> ACC_PRIVATE()) // The hidden_method method must have default access as it cannot be private...
{
ReportSemError(SemanticError::BAD_ACCESS_METHOD_OVERRIDE_EXTERNALLY,
class_declaration -> identifier_token,
(class_declaration -> NumInterfaces() > 0
? class_declaration -> Interface(class_declaration -> NumInterfaces() - 1) -> RightToken()
: (class_declaration -> super_opt ? class_declaration -> super_opt -> RightToken()
: class_declaration -> identifier_token)),
lex_stream -> NameString(class_declaration -> identifier_token),
method -> Header(),
StringConstant::US_private,
method -> containing_type -> ContainingPackage() -> PackageName(),
method -> containing_type -> ExternalName(),
hidden_method -> Header(),
StringConstant::US_default,
hidden_method -> containing_type -> ContainingPackage() -> PackageName(),
hidden_method -> containing_type -> ExternalName());
}
CheckInheritedMethodThrows(class_declaration, method, hidden_method);
return;
}
void Semantic::AddInheritedTypes(TypeSymbol *base_type, TypeSymbol *super_type)
{
ExpandedTypeTable &base_expanded_table = *(base_type -> expanded_type_table),
&super_expanded_table = *(super_type -> expanded_type_table);
for (int j = 0; j < super_expanded_table.symbol_pool.Length(); j++)
{
TypeShadowSymbol *type_shadow_symbol = super_expanded_table.symbol_pool[j];
TypeSymbol *type_symbol = type_shadow_symbol -> type_symbol;
//
// Note that since all fields in an interface are implicitly public, all other fields
// encountered here are enclosed in a type that is a super class of base_type.
//
if (type_symbol -> ACC_PUBLIC() ||
type_symbol -> ACC_PROTECTED() ||
((! type_symbol -> ACC_PRIVATE()) &&
(super_type -> ContainingPackage() == base_type -> ContainingPackage())))
{
NameSymbol *name_symbol = type_symbol -> Identity();
TypeShadowSymbol *shadow = base_expanded_table.FindTypeShadowSymbol(name_symbol);
if ((! shadow) || (shadow -> type_symbol -> owner != base_type))
{
if (! shadow)
shadow = base_expanded_table.InsertTypeShadowSymbol(type_symbol);
else shadow -> AddConflict(type_symbol);
if (type_symbol -> owner != super_type) // main type doesn't override all other fields? process conflicts.
{
for (int k = 0; k < type_shadow_symbol -> NumConflicts(); k++)
shadow -> AddConflict(type_shadow_symbol -> Conflict(k));
}
}
//
// TODO: maybe? if base_type is a nested type check if a type with the same
// name appears in one of the enclosed lexical scopes. If so, add
// it to the shadow!
//
}
}
return;
}
void Semantic::AddInheritedFields(TypeSymbol *base_type, TypeSymbol *super_type)
{
ExpandedFieldTable &base_expanded_table = *(base_type -> expanded_field_table),
&super_expanded_table = *(super_type -> expanded_field_table);
for (int i = 0; i < super_expanded_table.symbol_pool.Length(); i++)
{
VariableShadowSymbol *variable_shadow_symbol = super_expanded_table.symbol_pool[i];
VariableSymbol *variable_symbol = variable_shadow_symbol -> variable_symbol;
//
// Note that since all fields in an interface are implicitly public, all other fields
// encountered here are enclosed in a type that is a super class of base_type.
//
if (variable_symbol -> ACC_PUBLIC() ||
variable_symbol -> ACC_PROTECTED() ||
((! variable_symbol -> ACC_PRIVATE()) &&
(super_type -> ContainingPackage() == base_type -> ContainingPackage())))
{
NameSymbol *name_symbol = variable_symbol -> Identity();
VariableShadowSymbol *shadow = base_expanded_table.FindVariableShadowSymbol(name_symbol);
if ((! shadow) || (shadow -> variable_symbol -> owner != base_type))
{
if (! shadow)
shadow = base_expanded_table.InsertVariableShadowSymbol(variable_symbol);
else shadow -> AddConflict(variable_symbol);
if (variable_symbol -> owner != super_type) // main variable doesn't override all other fields? process conflicts.
{
for (int k = 0; k < variable_shadow_symbol -> NumConflicts(); k++)
shadow -> AddConflict(variable_shadow_symbol -> Conflict(k));
}
}
}
}
return;
}
void Semantic::AddInheritedMethods(TypeSymbol *base_type, TypeSymbol *super_type, LexStream::TokenIndex tok)
{
ExpandedMethodTable &base_expanded_table = *(base_type -> expanded_method_table),
&super_expanded_table = *(super_type -> expanded_method_table);
for (int k = 0; k < super_expanded_table.symbol_pool.Length(); k++)
{
MethodShadowSymbol *method_shadow_symbol = super_expanded_table.symbol_pool[k];
MethodSymbol *method = method_shadow_symbol -> method_symbol;
//
// Note that since all methods in an interface are implicitly
// public, all other methods encountered here are enclosed in a
// type that is a super class of base_type.
//
if (method -> ACC_PUBLIC() ||
method -> ACC_PROTECTED() ||
((! method -> ACC_PRIVATE()) &&
(super_type -> ContainingPackage() == base_type -> ContainingPackage())))
{
MethodShadowSymbol *base_method_shadow =
base_expanded_table.FindMethodShadowSymbol(method -> Identity());
if (! base_method_shadow)
base_expanded_table.InsertMethodShadowSymbol(method);
else
{
MethodShadowSymbol *shadow = base_expanded_table.FindOverloadMethodShadow(method, (Semantic *) this, tok);
if (! shadow)
base_expanded_table.Overload(base_method_shadow, method);
else
{
shadow -> AddConflict(method);
//
// If main method in question does not override all other methods,
// add all other conflicting methods.
//
if (method -> containing_type != super_type)
{
for (int i = 0; i < method_shadow_symbol -> NumConflicts(); i++)
shadow -> AddConflict(method_shadow_symbol -> Conflict(i));
}
}
}
}
else if (! (method -> ACC_PRIVATE() || method -> IsSynthetic())) // Not a method with default access from another package?
{
MethodShadowSymbol *base_method_shadow = base_expanded_table.FindMethodShadowSymbol(method -> Identity());
if (base_method_shadow)
{
MethodShadowSymbol *shadow = base_expanded_table.FindOverloadMethodShadow(method, (Semantic *) this, tok);
if (shadow)
{
LexStream::TokenIndex left_tok,
right_tok;
if (ThisType() == base_type)
{
AstMethodDeclaration *method_declaration = (AstMethodDeclaration *)
shadow -> method_symbol -> method_or_constructor_declaration;
AstMethodDeclarator *method_declarator = method_declaration -> method_declarator;
left_tok = method_declarator -> LeftToken();
right_tok = method_declarator -> RightToken();
}
else
{
AstInterfaceDeclaration *interface_declaration = ThisType() -> declaration -> InterfaceDeclarationCast();
AstClassDeclaration *class_declaration = ThisType() -> declaration -> ClassDeclarationCast();
if (interface_declaration)
{
left_tok = right_tok = interface_declaration -> identifier_token;
}
else if (class_declaration)
{
left_tok = right_tok = class_declaration -> identifier_token;
}
else
{
AstClassInstanceCreationExpression *class_creation = ThisType() -> declaration
-> ClassInstanceCreationExpressionCast();
assert(class_creation);
left_tok = class_creation -> class_type -> LeftToken();
right_tok = class_creation -> class_type -> RightToken();
}
}
if (! method -> IsTyped())
method -> ProcessMethodSignature((Semantic *) this, tok);
ReportSemError(SemanticError::DEFAULT_METHOD_NOT_OVERRIDDEN,
left_tok,
right_tok,
method -> Header(),
base_type -> ContainingPackage() -> PackageName(),
base_type -> ExternalName(),
super_type -> ContainingPackage() -> PackageName(),
super_type -> ExternalName());
}
}
}
}
return;
}
void Semantic::ComputeTypesClosure(TypeSymbol *type, LexStream::TokenIndex tok)
{
type -> expanded_type_table = new ExpandedTypeTable();
TypeSymbol *super_class = type -> super;
if (super_class)
{
if (! super_class -> expanded_type_table)
ComputeTypesClosure(super_class, tok);
}
for (int j = 0; j < type -> NumInterfaces(); j++)
{
TypeSymbol *interf = type -> Interface(j);
if (! interf -> expanded_type_table)
ComputeTypesClosure(interf, tok);
}
if (! type -> NestedTypesProcessed())
type -> ProcessNestedTypeSignatures((Semantic *) this, tok);
for (int i = 0; i < type -> NumTypeSymbols(); i++)
{
if (! type -> TypeSym(i) -> Bad())
type -> expanded_type_table -> InsertTypeShadowSymbol(type -> TypeSym(i));
}
if (super_class)
AddInheritedTypes(type, super_class);
for (int k = 0; k < type -> NumInterfaces(); k++)
AddInheritedTypes(type, type -> Interface(k));
type -> expanded_type_table -> CompressSpace();
return;
}
void Semantic::ComputeFieldsClosure(TypeSymbol *type, LexStream::TokenIndex tok)
{
type -> expanded_field_table = new ExpandedFieldTable();
TypeSymbol *super_class = type -> super;
if (super_class)
{
if (! super_class -> expanded_field_table)
ComputeFieldsClosure(super_class, tok);
}
for (int j = 0; j < type -> NumInterfaces(); j++)
{
TypeSymbol *interf = type -> Interface(j);
if (! interf -> expanded_field_table)
ComputeFieldsClosure(interf, tok);
}
assert(type -> FieldMembersProcessed());
for (int i = 0; i < type -> NumVariableSymbols(); i++)
{
VariableSymbol *variable = type -> VariableSym(i);
type -> expanded_field_table -> InsertVariableShadowSymbol(variable);
}
//
// As the type Object which is the super type of all interfaces does
// not contain any field declarations, we don't have to do any special
// check here as we have to when computing method closures.
//
if (super_class)
AddInheritedFields(type, super_class);
for (int k = 0; k < type -> NumInterfaces(); k++)
AddInheritedFields(type, type -> Interface(k));
type -> expanded_field_table -> CompressSpace();
return;
}
void Semantic::ComputeMethodsClosure(TypeSymbol *type, LexStream::TokenIndex tok)
{
type -> expanded_method_table = new ExpandedMethodTable();
TypeSymbol *super_class = type -> super;
if (super_class)
{
if (! super_class -> expanded_method_table)
ComputeMethodsClosure(super_class, tok);
}
for (int j = 0; j < type -> NumInterfaces(); j++)
{
TypeSymbol *interf = type -> Interface(j);
if (! interf -> expanded_method_table)
ComputeMethodsClosure(interf, tok);
}
assert(type -> MethodMembersProcessed());
for (int i = 0; i < type -> NumMethodSymbols(); i++)
{
MethodSymbol *method = type -> MethodSym(i);
//
// If the method in question is neither a constructor nor an
// initializer, then ...
// if (method -> Identity() != control.init_name_symbol &&
// method -> Identity() != control.block_init_name_symbol &&
// method -> Identity() != control.clinit_name_symbol)
//
if (*(method -> Name()) != U_LESS)
{
type -> expanded_method_table -> Overload(method);
}
}
if (super_class && (! type -> ACC_INTERFACE()))
AddInheritedMethods(type, super_class, tok);
for (int k = 0; k < type -> NumInterfaces(); k++)
AddInheritedMethods(type, type -> Interface(k), tok);
if (type -> ACC_INTERFACE()) // the super class is Object
AddInheritedMethods(type, control.Object(), tok);
type -> expanded_method_table -> CompressSpace();
return;
}
void Semantic::ProcessFormalParameters(BlockSymbol *block, AstMethodDeclarator *method_declarator)
{
for (int i = 0; i < method_declarator -> NumFormalParameters(); i++)
{
AstFormalParameter *parameter = method_declarator -> FormalParameter(i);
AstArrayType *array_type = parameter -> type -> ArrayTypeCast();
Ast *actual_type = (array_type ? array_type -> type : parameter -> type);
AccessFlags access_flags = ProcessFormalModifiers(parameter);
AstPrimitiveType *primitive_type = actual_type -> PrimitiveTypeCast();
TypeSymbol *parm_type = (primitive_type ? FindPrimitiveType(primitive_type) : MustFindType(actual_type));
AstVariableDeclaratorId *name = parameter -> formal_declarator -> variable_declarator_name;
NameSymbol *name_symbol = lex_stream -> NameSymbol(name -> identifier_token);
VariableSymbol *symbol = block -> FindVariableSymbol(name_symbol);
if (symbol)
{
ReportSemError(SemanticError::DUPLICATE_FORMAL_PARAMETER,
name -> identifier_token,
name -> identifier_token,
name_symbol -> Name());
}
else symbol = block -> InsertVariableSymbol(name_symbol);
int num_dimensions = (array_type ? array_type -> NumBrackets() : 0) + name -> NumBrackets();
if (num_dimensions == 0)
symbol -> SetType(parm_type);
else symbol -> SetType(parm_type -> GetArrayType((Semantic *) this, num_dimensions));
symbol -> SetFlags(access_flags);
symbol -> MarkComplete();
parameter -> formal_declarator -> symbol = symbol;
}
return;
}
void Semantic::ProcessMethodDeclaration(AstMethodDeclaration *method_declaration)
{
TypeSymbol *this_type = ThisType();
AccessFlags access_flags = (this_type -> ACC_INTERFACE()
? ProcessAbstractMethodModifiers(method_declaration)
: ProcessMethodModifiers(method_declaration));
//
// TODO: File Query Sun on that one. We no longer explicitly mark such methods as final
// as it appears that some tools expect these methods to remain unmarked.
//
//
// A private method and all methods declared in a final class are implicitly final.
//
// if (access_flags.ACC_PRIVATE() || this_type -> ACC_FINAL())
// access_flags.SetACC_FINAL();
//
//
// A method enclosed in an inner type may not be declared static.
//
if (access_flags.ACC_STATIC() && this_type -> IsInner())
{
AstModifier *modifier = NULL;
for (int i = 0; i < method_declaration -> NumMethodModifiers(); i++)
{
if (method_declaration -> MethodModifier(i) -> kind == Ast::STATIC)
modifier = method_declaration -> MethodModifier(i);
}
assert(modifier);
ReportSemError(SemanticError::STATIC_METHOD_IN_INNER_CLASS,
modifier -> modifier_kind_token,
modifier -> modifier_kind_token);
}
//
//
//
AstArrayType *array_type = method_declaration -> type -> ArrayTypeCast();
Ast *actual_type = (array_type ? array_type -> type : method_declaration -> type);
AstPrimitiveType *primitive_type = actual_type -> PrimitiveTypeCast();
TypeSymbol *method_type = (primitive_type ? FindPrimitiveType(primitive_type) : MustFindType(actual_type));
AstMethodDeclarator *method_declarator = method_declaration -> method_declarator;
if (method_declarator -> NumBrackets() > 0)
{
if (method_type == control.void_type)
ReportSemError(SemanticError::VOID_ARRAY,
method_declaration -> type -> LeftToken(),
method_declarator -> RightToken());
else ReportSemError(SemanticError::OBSOLESCENT_BRACKETS,
method_declarator -> LeftToken(),
method_declarator -> RightToken());
}
NameSymbol *name_symbol = lex_stream -> NameSymbol(method_declarator -> identifier_token);
if (name_symbol == this_type -> Identity())
{
ReportSemError(SemanticError::METHOD_WITH_CONSTRUCTOR_NAME,
method_declaration -> type -> LeftToken(),
method_declarator -> identifier_token,
name_symbol -> Name());
}
//
// As the body of the method may not have been parsed yet, we estimate a size
// for its symbol table based on the number of lines in the body + a margin for one-liners.
//
BlockSymbol *block_symbol = new BlockSymbol(method_declarator -> NumFormalParameters());
block_symbol -> max_variable_index = (access_flags.ACC_STATIC() ? 0 : 1);
ProcessFormalParameters(block_symbol, method_declarator);
MethodSymbol *method = this_type -> FindMethodSymbol(name_symbol);
if (! method)
method = this_type -> InsertMethodSymbol(name_symbol);
else
{
if (this_type -> FindOverloadMethod(method, method_declarator))
{
ReportSemError(SemanticError::DUPLICATE_METHOD,
method_declarator -> LeftToken(),
method_declarator -> RightToken(),
name_symbol -> Name(),
this_type -> Name());
delete block_symbol;
return;
}
method = this_type -> Overload(method);
}
int num_dimensions = (method_type == control.void_type
? 0
: (array_type ? array_type -> NumBrackets() : 0) + method_declarator -> NumBrackets());
if (num_dimensions == 0)
method -> SetType(method_type);
else method -> SetType(method_type -> GetArrayType((Semantic *) this, num_dimensions));
//
// if the method is not static, leave a slot for the "this" pointer.
//
method -> SetFlags(access_flags);
method -> SetContainingType(this_type);
method -> SetBlockSymbol(block_symbol);
method -> method_or_constructor_declaration = method_declaration;
for (int i = 0; i < method_declarator -> NumFormalParameters(); i++)
{
AstVariableDeclarator *formal_declarator = method_declarator -> FormalParameter(i) -> formal_declarator;
VariableSymbol *symbol = formal_declarator -> symbol;
symbol -> SetOwner(method);
symbol -> SetLocalVariableIndex(block_symbol -> max_variable_index++);
if (control.IsDoubleWordType(symbol -> Type()))
block_symbol -> max_variable_index++;
symbol -> declarator = formal_declarator;
method -> AddFormalParameter(symbol);
}
method -> SetSignature(control);
for (int k = 0; k < method_declaration -> NumThrows(); k++)
{
AstExpression *throw_expression = method_declaration -> Throw(k);
TypeSymbol *throw_type = MustFindType(throw_expression);
throw_expression -> symbol = throw_type;
method -> AddThrows(throw_type);
}
method_declaration -> method_symbol = method; // save for processing bodies later.
if (method -> ACC_ABSTRACT() && (! this_type -> ACC_ABSTRACT()))
{
ReportSemError(SemanticError::NON_ABSTRACT_TYPE_CONTAINS_ABSTRACT_METHOD,
method_declaration -> LeftToken(),
method_declarator -> identifier_token,
name_symbol -> Name(),
this_type -> Name());
}
if (lex_stream -> IsDeprecated(lex_stream -> Previous(method_declaration -> LeftToken())))
method -> MarkDeprecated();
return;
}
//
// Search for simple identifier which is supposed to be a type.
// If it is not found, issue an error message.
//
TypeSymbol *Semantic::FindPrimitiveType(AstPrimitiveType *primitive_type)
{
switch(primitive_type -> kind)
{
case Ast::INT:
return control.int_type;
case Ast::DOUBLE:
return control.double_type;
case Ast::CHAR:
return control.char_type;
case Ast::LONG:
return control.long_type;
case Ast::FLOAT:
return control.float_type;
case Ast::BYTE:
return control.byte_type;
case Ast::SHORT:
return control.short_type;
case Ast::BOOLEAN:
return control.boolean_type;
default:
break;
}
return control.void_type;
}
TypeSymbol *Semantic::ImportType(LexStream::TokenIndex identifier_token, NameSymbol *name_symbol)
{
TypeSymbol *type = NULL;
PackageSymbol *package = NULL;
FileSymbol *file_symbol = NULL;
for (int i = 0; i < import_on_demand_packages.Length(); i++)
{
PackageSymbol *import_package = import_on_demand_packages[i] -> PackageCast();
if (import_package)
{
FileSymbol *symbol = Control::GetFile(control, import_package, name_symbol);
if (symbol)
{
if (! package)
{
file_symbol = symbol;
package = import_package;
}
else
{
ReportSemError(SemanticError::DUPLICATE_ON_DEMAND_IMPORT,
identifier_token,
identifier_token,
name_symbol -> Name(),
package -> PackageName(),
import_package -> PackageName());
}
}
}
else
{
TypeSymbol *import_type = (TypeSymbol *) import_on_demand_packages[i];
if (! import_type -> expanded_type_table)
ComputeTypesClosure(import_type, identifier_token);
TypeShadowSymbol *type_shadow_symbol = import_type -> expanded_type_table -> FindTypeShadowSymbol(name_symbol);
if (type_shadow_symbol)
type = FindTypeInShadow(type_shadow_symbol, identifier_token);
}
}
if (! type)
{
if (package)
{
type = package -> FindTypeSymbol(name_symbol);
if (! type)
type = ReadType(file_symbol, package, name_symbol, identifier_token);
else if (type -> SourcePending())
control.ProcessHeaders(type -> file_symbol);
}
}
if (type && (! (type -> ACC_PUBLIC() || type -> ContainingPackage() == this_package)))
ReportTypeInaccessible(identifier_token, identifier_token, type);
return type;
}
TypeSymbol *Semantic::FindType(LexStream::TokenIndex identifier_token)
{
TypeSymbol *type;
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
SemanticEnvironment *env;
for (env = state_stack.Top(); env; env = env -> previous)
{
type = env -> symbol_table.FindTypeSymbol(name_symbol);
if (type)
break;
type = env -> Type();
if (name_symbol == type -> Identity()) // Recall that a type may not have the same name as one of its enclosing types.
break;
if (! type -> expanded_type_table)
ComputeTypesClosure(type, identifier_token);
TypeShadowSymbol *type_shadow_symbol = type -> expanded_type_table -> FindTypeShadowSymbol(name_symbol);
if (type_shadow_symbol)
{
type = FindTypeInShadow(type_shadow_symbol, identifier_token);
break;
}
}
if (env) // The type was found in some enclosing environment?
{
//
// If the type is an inherited type, make sure that there is not a
// type of the same name within an enclosing lexical scope.
//
if (type -> owner -> TypeCast() && type -> owner != env -> Type())
{
for (SemanticEnvironment *env2 = env -> previous; env2; env2 = env2 -> previous)
{
TypeSymbol *outer_type = env2 -> symbol_table.FindTypeSymbol(name_symbol); // check local type
if (! outer_type) // if local type not found, check inner type...
{
if (! env2 -> Type() -> expanded_type_table)
ComputeTypesClosure(env2 -> Type(), identifier_token);
TypeShadowSymbol *type_shadow_symbol = env2 -> Type() -> expanded_type_table
-> FindTypeShadowSymbol(name_symbol);
if (type_shadow_symbol)
outer_type = FindTypeInShadow(type_shadow_symbol, identifier_token);
}
//
// If a different type of the same name was found in an enclosing scope.
//
if (outer_type && outer_type != type)
{
MethodSymbol *method = outer_type -> owner -> MethodCast();
if (method)
{
ReportSemError(SemanticError::INHERITANCE_AND_LEXICAL_SCOPING_CONFLICT_WITH_LOCAL,
identifier_token,
identifier_token,
lex_stream -> NameString(identifier_token),
env -> Type() -> ContainingPackage() -> PackageName(),
env -> Type() -> ExternalName(),
method -> Name());
break;
}
else
{
ReportSemError(SemanticError::INHERITANCE_AND_LEXICAL_SCOPING_CONFLICT_WITH_MEMBER,
identifier_token,
identifier_token,
lex_stream -> NameString(identifier_token),
env -> Type() -> ContainingPackage() -> PackageName(),
env -> Type() -> ExternalName(),
env2 -> Type() -> ContainingPackage() -> PackageName(),
env2 -> Type() -> ExternalName());
break;
}
}
}
}
return type;
}
//
// check whether or not the type is in the current compilation unit
// either because it was declared as a class or interface or it was
// imported by a single-type-import declaration.
//
for (int i = 0; i < single_type_imports.Length(); i++)
{
type = single_type_imports[i];
if (name_symbol == type -> Identity())
return type;
}
//
// If a package was specified in this file (the one we are compiling),
// we look for the type requested inside the package in question.
// Otherwise, we look for the type requested in the unnamed package.
// If we don't find the type or we find a bad type we check to see
// if the type can be imported.
//
PackageSymbol *package = (compilation_unit -> package_declaration_opt ? this_package : control.unnamed_package);
type = FindSimpleNameType(package, identifier_token);
TypeSymbol *imported_type = ((! type ) || type -> Bad() ? ImportType(identifier_token, name_symbol) : (TypeSymbol *) NULL);
//
// If a valid type can be imported on demand, chose that type.
// Otherwise, if a type was found at all, do some final checks on it.
//
// Note that a type T contained in a package P is always accessible to all other
// types contained in P. I.e., we do not need to perform access check for type...
//
//
if (imported_type)
type = imported_type;
else if (type)
{
//
// If a type T was specified in a source file that is not called T.java
// but X.java (where X != T) and we are not currently compiling file X,
// issue a warning to alert the user that in some circumstances, this
// may not be visible. (i.e., if the file X has not yet been compiled,
// then T is invisile as the compiler will only look for T in T.java.)
//
FileSymbol *file_symbol = type -> file_symbol;
if (file_symbol && (type -> Identity() != file_symbol -> Identity()) && (file_symbol != this -> source_file_symbol))
{
ReportSemError(SemanticError::REFERENCE_TO_TYPE_IN_MISMATCHED_FILE,
identifier_token,
identifier_token,
type -> Name(),
file_symbol -> Name());
}
}
return type;
}
//
//
//
TypeSymbol *Semantic::MustFindType(Ast *name)
{
TypeSymbol *type;
LexStream::TokenIndex identifier_token;
AstSimpleName *simple_name = name -> SimpleNameCast();
if (simple_name)
{
identifier_token = simple_name -> identifier_token;
type = FindType(identifier_token);
//
// If the type was not found, try to read it again to generate an appropriate error message.
//
if (! type)
{
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
PackageSymbol *package = (compilation_unit -> package_declaration_opt ? this_package : control.unnamed_package);
FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
//
// If there is no file associated with the name of the type then the type does
// not exist. Before invoking ReadType to issue a "type not found" error message,
// check whether or not the user is not attempting to access an inaccessible
// private type.
//
if ((! file_symbol) && state_stack.Size() > 0)
{
for (TypeSymbol *super_type = ThisType() -> super; super_type; super_type = super_type -> super)
{
assert(super_type -> expanded_type_table);
TypeShadowSymbol *type_shadow_symbol = super_type -> expanded_type_table -> FindTypeShadowSymbol(name_symbol);
if (type_shadow_symbol)
{
type = FindTypeInShadow(type_shadow_symbol, identifier_token);
break;
}
}
}
if (type)
ReportTypeInaccessible(name -> LeftToken(), name -> RightToken(), type);
else type = ReadType(file_symbol, package, name_symbol, identifier_token);
}
else
{
TypeAccessCheck(name, type);
}
}
else
{
AstFieldAccess *field_access = name -> FieldAccessCast();
assert(field_access);
identifier_token = field_access -> identifier_token;
ProcessPackageOrType(field_access -> base);
Symbol *symbol = field_access -> base -> symbol;
type = symbol -> TypeCast();
if (type)
{
TypeNestAccessCheck(field_access -> base);
type = MustFindNestedType(type, field_access);
}
else
{
PackageSymbol *package = symbol -> PackageCast();
if (package -> directory.Length() == 0)
{
ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
field_access -> base -> LeftToken(),
field_access -> base -> RightToken(),
package -> PackageName());
}
NameSymbol *name_symbol = lex_stream -> NameSymbol(identifier_token);
type = package -> FindTypeSymbol(name_symbol);
if (! type)
{
FileSymbol *file_symbol = Control::GetFile(control, package, name_symbol);
type = ReadType(file_symbol, package, name_symbol, identifier_token);
}
else
{
if (type -> SourcePending())
control.ProcessHeaders(type -> file_symbol);
TypeAccessCheck(name, type);
}
}
}
//
// Establish a dependence from the base_type to a type that it "must find".
// Note that the only time an environment is not available is when were are
// processing the type header of an outermost type.
//
if (state_stack.Size() > 0)
AddDependence(ThisType(), type, identifier_token);
//
//
//
if (control.option.deprecation && type -> IsDeprecated() && type -> file_symbol != source_file_symbol)
{
ReportSemError(SemanticError::DEPRECATED_TYPE,
name -> LeftToken(),
name -> RightToken(),
type -> ContainingPackage() -> PackageName(),
type -> ExternalName());
}
return type;
}
void Semantic::ProcessInterface(TypeSymbol *base_type, AstExpression *name)
{
TypeSymbol *interf = MustFindType(name);
assert(! interf -> SourcePending());
if (! interf -> ACC_INTERFACE())
{
if (! interf -> Bad())
{
ReportSemError(SemanticError::NOT_AN_INTERFACE,
name -> LeftToken(),
name -> RightToken(),
interf -> ContainingPackage() -> PackageName(),
interf -> ExternalName());
}
name -> symbol = NULL;
}
else
{
for (int k = 0; k < base_type -> NumInterfaces(); k++)
{
if (base_type -> Interface(k) == interf)
{
ReportSemError(SemanticError::DUPLICATE_INTERFACE,
name -> LeftToken(),
name -> RightToken(),
interf -> ContainingPackage() -> PackageName(),
interf -> ExternalName(),
base_type -> ExternalName());
name -> symbol = NULL;
return;
}
}
name -> symbol = interf; // save type name in ast.
base_type -> AddInterface(interf);
}
return;
}
void Semantic::InitializeVariable(AstFieldDeclaration *field_declaration, Tuple<VariableSymbol *> &finals)
{
ThisMethod() = NULL;
for (int i = 0; i < field_declaration -> NumVariableDeclarators(); i++)
{
AstVariableDeclarator *variable_declarator = field_declaration -> VariableDeclarator(i);
if ((ThisVariable() = variable_declarator -> symbol))
{
if (variable_declarator -> variable_initializer_opt)
{
variable_declarator -> pending = true;
int start_num_errors = NumErrors();
ProcessVariableInitializer(variable_declarator);
if (NumErrors() == start_num_errors)
DefiniteVariableInitializer(variable_declarator, finals);
else variable_declarator -> symbol -> MarkDefinitelyAssigned(); // assume variable is assigned
variable_declarator -> pending = false;
}
ThisVariable() -> MarkComplete();
}
}
return;
}
inline void Semantic::ProcessInitializer(AstBlock *initializer_block, AstBlock *block_body,
MethodSymbol *init_method, Tuple<VariableSymbol *> &finals)
{
ThisVariable() = NULL;
ThisMethod() = init_method;
LocalBlockStack().Push(initializer_block);
LocalSymbolTable().Push(init_method -> block_symbol -> Table());
int start_num_errors = NumErrors();
AstConstructorBlock *constructor_block = block_body -> ConstructorBlockCast();
if (constructor_block)
{
assert(constructor_block -> explicit_constructor_invocation_opt);
ReportSemError(SemanticError::MISPLACED_EXPLICIT_CONSTRUCTOR_INVOCATION,
constructor_block -> explicit_constructor_invocation_opt -> LeftToken(),
constructor_block -> explicit_constructor_invocation_opt -> RightToken());
}
ProcessBlock(block_body);
if (NumErrors() == start_num_errors)
DefiniteBlockInitializer(block_body, LocalBlockStack().max_size, finals);
//
// If an enclosed block has a higher max_variable_index than the current block,
// update max_variable_index in the current_block, accordingly.
//
if (init_method -> block_symbol -> max_variable_index < LocalBlockStack().TopMaxEnclosedVariableIndex())
init_method -> block_symbol -> max_variable_index = LocalBlockStack().TopMaxEnclosedVariableIndex();
LocalBlockStack().Pop();
LocalSymbolTable().Pop();
return;
}
bool Semantic::NeedsInitializationMethod(AstFieldDeclaration *field_declaration)
{
//
// We need a static constructor-initializer if we encounter at least one class
// variable that is declared with an initializer is not a constant expression.
//
for (int i = 0; i < field_declaration -> NumVariableDeclarators(); i++)
{
AstVariableDeclarator *variable_declarator = field_declaration -> VariableDeclarator(i);
if (variable_declarator -> variable_initializer_opt)
{
AstExpression *init = variable_declarator -> variable_initializer_opt -> ExpressionCast();
if (! (init && init -> IsConstant()))
return true;
//
// TODO: there seems to be a contradiction between the language spec and the VM spec.
// The language spec seems to require that a variable be initialized (in the class file)
// with a "ConstantValue" only if it is static. The VM spec, on the other hand, states
// that a static need not be final to be initialized with a ConstantValue.
// As of now, we are following the language spec - ergo, this extra test.
//
if (variable_declarator -> symbol && (! variable_declarator -> symbol -> ACC_FINAL()))
return true;
}
}
return false;
}
void Semantic::ProcessStaticInitializers(AstClassBody *class_body)
{
if (class_body -> NumStaticInitializers() > 0 || class_body -> NumClassVariables() > 0)
{
TypeSymbol *this_type = ThisType();
BlockSymbol *block_symbol = new BlockSymbol(0); // the symbol table associated with this block will contain no element
block_symbol -> max_variable_index = 0; // if we need this, it will be associated with a static function.
AstBlock *initializer_block = compilation_unit -> ast_pool -> GenBlock();
initializer_block -> left_brace_token = class_body -> left_brace_token;
initializer_block -> right_brace_token = class_body -> left_brace_token;
initializer_block -> block_symbol = block_symbol;
initializer_block -> nesting_level = LocalBlockStack().Size();
LocalBlockStack().max_size = 0;
//
// If the class being processed contains any static
// initializer then, it needs a static initializer function?
//
MethodSymbol *init_method = NULL;
if (class_body -> NumStaticInitializers() > 0)
{
init_method = this_type -> InsertMethodSymbol(control.clinit_name_symbol);
init_method -> SetType(control.void_type);
init_method -> SetACC_FINAL();
init_method -> SetACC_STATIC();
init_method -> SetContainingType(this_type);
init_method -> SetBlockSymbol(block_symbol);
init_method -> SetSignature(control);
}
//
// Compute the set of final variables declared by the user in this type.
//
Tuple<VariableSymbol *> finals(this_type -> NumVariableSymbols());
for (int i = 0; i < this_type -> NumVariableSymbols(); i++)
{
VariableSymbol *variable_symbol = this_type -> VariableSym(i);
if (variable_symbol -> ACC_FINAL())
finals.Next() = variable_symbol;
}
//
// The static initializers and class variable initializers are executed in textual order... 8.5
//
int j,
k;
for (j = 0, k = 0; j < class_body -> NumClassVariables() && k < class_body -> NumStaticInitializers(); )
{
//
// Note that since there cannot be any overlap in the
// declarations, we can use either location position.
// The RightToken of the field declaration is used because it
// does not have to be computed (it is the terminating semicolon).
// Similarly, the LeftToken of the static initializer is used
// because it is the initial "static" keyword that marked the initializer.
//
// if (class_body -> InstanceVariables(j) -> RightToken() < class_body -> Block(k) -> LeftToken())
//
if (class_body -> ClassVariable(j) -> semicolon_token < class_body -> StaticInitializer(k) -> static_token)
{
InitializeVariable(class_body -> ClassVariable(j), finals);
j++;
}
else
{
AstBlock *block_body = class_body -> StaticInitializer(k) -> block;
//
// The first block that is the body of an initializer is reachable
// A subsequent block is reachable iff its predecessor can complete
// normally
//
block_body -> is_reachable = (k == 0
? true
: class_body -> StaticInitializer(k - 1) -> block -> can_complete_normally);
ProcessInitializer(initializer_block, block_body, init_method, finals);
k++;
}
}
for (; j < class_body -> NumClassVariables(); j++)
InitializeVariable(class_body -> ClassVariable(j), finals);
for (; k < class_body -> NumStaticInitializers(); k++)
{
AstBlock *block_body = class_body -> StaticInitializer(k) -> block;
//
// The first block that is the body of an initializer is reachable
// A subsequent block is reachable iff its predecessor can complete
// normally
//
block_body -> is_reachable = (k == 0
? true
: class_body -> StaticInitializer(k - 1) -> block -> can_complete_normally);
ProcessInitializer(initializer_block, block_body, init_method, finals);
}
//
// Check that each static final variables has been initialized by now.
// If not, issue an error and assume it is.
//
for (int l = 0; l < finals.Length(); l++)
{
if (finals[l] -> ACC_STATIC() && (! finals[l] -> IsDefinitelyAssigned()))
{
ReportSemError(SemanticError::UNINITIALIZED_STATIC_FINAL_VARIABLE,
finals[l] -> declarator -> LeftToken(),
finals[l] -> declarator -> RightToken());
finals[l] -> MarkDefinitelyAssigned();
}
}
//
// If we had not yet defined a static initializer function and
// there exists a static variable in the class that is not initialized
// with a constant then define one now.
//
if (! init_method)
{
//
// Check whether or not we need a static initializer method. We need a static
// constructor-initializer iff:
//
// . we have at least one static initializer (this case is processed above)
// . we have at least one static variable that is not initialized with a
// constant expression.
//
for (int i = 0; i < class_body -> NumClassVariables(); i++)
{
if (NeedsInitializationMethod(class_body -> ClassVariable(i)))
{
init_method = this_type -> InsertMethodSymbol(control.clinit_name_symbol);
init_method -> SetType(control.void_type);
init_method -> SetACC_FINAL();
init_method -> SetACC_STATIC();
init_method -> SetContainingType(this_type);
init_method -> SetBlockSymbol(block_symbol);
init_method -> SetSignature(control);
break;
}
}
}
//
// If an initialization method has been defined, update its max_block_depth.
// Otherwise, deallocate the block symbol as nobody would be pointing to it
// after this point.
//
if (init_method)
{
init_method -> max_block_depth = LocalBlockStack().max_size;
this_type -> static_initializer_method = init_method;
block_symbol -> CompressSpace(); // space optimization
}
else delete block_symbol;
// STG:
// delete initializer_block;
}
return;
}
void Semantic::ProcessBlockInitializers(AstClassBody *class_body)
{
TypeSymbol *this_type = ThisType();
//
// Compute the set of final variables declared by the user in this type.
//
Tuple<VariableSymbol *> finals(this_type -> NumVariableSymbols());
for (int i = 0; i < this_type -> NumVariableSymbols(); i++)
{
VariableSymbol *variable_symbol = this_type -> VariableSym(i);
if (variable_symbol -> ACC_FINAL())
finals.Next() = variable_symbol;
}
//
// Initialization code is executed by every constructor, just after the
// superclass constructor is called, in textual order along with any
// instance variable initializations.
//
if (class_body -> NumBlocks() == 0)
{
for (int j = 0; j < class_body -> NumInstanceVariables(); j++)
InitializeVariable(class_body -> InstanceVariable(j), finals);
}
else
{
MethodSymbol *init_method = this_type -> InsertMethodSymbol(control.block_init_name_symbol);
init_method -> SetType(control.void_type);
init_method -> SetACC_FINAL();
init_method -> SetACC_PRIVATE();
init_method -> SetContainingType(this_type);
init_method -> SetBlockSymbol(new BlockSymbol(0)); // the symbol table associated with this block will contain no element
init_method -> block_symbol -> max_variable_index = 1;
init_method -> SetSignature(control);
//
// Compute the set of constructors whose bodies do not start with
// an explicit this call.
//
for (int i = 0; i < class_body -> NumConstructors(); i++)
{
MethodSymbol *method = class_body -> Constructor(i) -> constructor_symbol;
if (method)
{
AstConstructorBlock *constructor_block = class_body -> Constructor(i) -> constructor_body;
if (! (constructor_block -> explicit_constructor_invocation_opt &&
constructor_block -> explicit_constructor_invocation_opt -> ThisCallCast()))
init_method -> AddInitializerConstructor(method);
}
}
this_type -> block_initializer_method = init_method;
AstBlock *initializer_block = compilation_unit -> ast_pool -> GenBlock();
initializer_block -> left_brace_token = class_body -> left_brace_token;
initializer_block -> right_brace_token = class_body -> left_brace_token;
initializer_block -> block_symbol = init_method -> block_symbol;
initializer_block -> nesting_level = LocalBlockStack().Size();
LocalBlockStack().max_size = 0;
int j,
k;
for (j = 0, k = 0; j < class_body -> NumInstanceVariables() && k < class_body -> NumBlocks(); )
{
//
// Note that since there cannot be any overlap in the
// declarations, we can use either location position.
// The RightToken of the field declaration is used because it
// does not have to be computed (it is the terminating semicolon).
// Similarly, the LeftToken of the block initializer is used
// because it is the initial "{".
//
// if (class_body -> InstanceVariable(j) -> RightToken() < class_body -> Blocks(k) -> LeftToken())
//
if (class_body -> InstanceVariable(j) -> semicolon_token < class_body -> Block(k) -> left_brace_token)
{
InitializeVariable(class_body -> InstanceVariable(j), finals);
j++;
}
else
{
AstBlock *block_body = class_body -> Block(k);
//
// The first block that is the body of an initializer is reachable
// A subsequent block is reachable iff its predecessor can complete
// normally
//
block_body -> is_reachable = (k == 0 ? true : class_body -> Block(k - 1) -> can_complete_normally);
ProcessInitializer(initializer_block, block_body, init_method, finals);
k++;
}
}
for (; j < class_body -> NumInstanceVariables(); j++)
InitializeVariable(class_body -> InstanceVariable(j), finals);
for (; k < class_body -> NumBlocks(); k++)
{
AstBlock *block_body = class_body -> Block(k);
//
// The first block that is the body of an initializer is reachable
// A subsequent block is reachable iff its predecessor can complete
// normally
//
block_body -> is_reachable = (k == 0 ? true : class_body -> Block(k - 1) -> can_complete_normally);
ProcessInitializer(initializer_block, block_body, init_method, finals);
}
init_method -> max_block_depth = LocalBlockStack().max_size;
init_method -> block_symbol -> CompressSpace(); // space optimization
//
// Note that unlike the case of static fields. We do not ensure here that
// each final instance variable has been initialized at this point, because
// the user may chose instead to initialize such a final variable in every
// constructor instead. See body.cpp
//
// STG:
// delete initializer_block;
}
return;
}